本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 [署名 4.0 国际 (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/deed.zh) 本文作者: 苏洋 创建时间: 2022年02月23日 统计字数: 10635字 阅读时间: 22分钟阅读 本文链接: https://soulteary.com/2022/02/23/building-a-personal-bookmark-navigation-app-from-scratch-flare.html ----- # 从零开始搭建个人书签导航应用:Flare 本篇文章中,我将介绍如何快速的在 Docker 中使用 Flare 这个轻巧、美观,并且用户隐私优先、100% 数据用户自己掌控的书签导航工具。 如果你熟悉 Docker,那么你将能够在十分钟内拥有属于自己的书签导航;如果你是一个新手,也没关系。跟着文章一步步操作,大概半个小时,你将能够将 Flare 运行在 Docker 之中,步入容器世界的大门。 ## 写在前面 在上一篇文章[《使用 Docker 搭建适用于 HomeLab 的书签导航》](https://soulteary.com/2022/02/08/building-bookmark-navigation-for-homelab-with-docker.html)的开头中,我曾提到过一些我过去使用书签导航工具的状况:在使用 Chrome 的十几年里,上千个书签慢慢的出现在了收藏夹里,然后和现实中放在书柜里的书一样,慢慢的蒙上了厚厚的灰尘。 ![现实中吃灰的知识“收藏夹” / 图片来自 kropekk\_pl@pixabay](https://attachment.soulteary.com/2022/02/17/book-with-dust.jpg) 几个月前,我开始进行个人的 PKM 重建,其中有一部分是关于书签的使用。实话说,我对于当前书签程序并不是特别满意,主要有几个原因: 我希望这个工具能够**更高效和更简单**,而不是只有极少数内容在书签栏呈现,更多的内容需要在层层“文件夹”中翻找,或者需要绞尽脑汁,通过在搜索栏中碰运气,看看能不能靠关键词和自动补全来匹配出具体内容。**猜测和翻找都太浪费时间了**。 我希望这些数据都是**私有化的、少一些不确定因素**。作为一个使用了各种互联网产品二十多年的“年轻人”,看到过太多工具和公司的生生死死、浮浮沉沉。不少在线服务和软件背后的公司慢慢变成了时间长河里的一粒沙,在产品和公司陨落的过程中,用户的数据则经常变成陪葬品。**数据随着产品一起消失,这是我不愿意看到的**。 我希望软件能够**通用一些**,书签数据不应该掺和浏览器打架,也跟着玩“生殖隔离”。只能在 Chrome中、或者只能在 Safari、IE 中使用的工具和插件,总让我有一种数据被绑架的感觉。即使我绝大多数情况下只用 Chrome,但是我依旧希望在我打开 Safari 的时候,也能够用鼠标“指指点点”这些书签,快速的到达我想要去的地方。(我对浏览器之间的书签导入功能持保留态度,因为曾经在 Chrome、Firefox、国产浏览器之间迁移的时候,出现了“书签大乱斗”、“书签影分身”这类意外。) 在尝试了使用各种软件之后,我把目光锁定在了一个波兰程序员小哥的项目上(Flame)。在深入使用这个软件,重构了一部分代码、封装了容器应用,并提交了几个 PR 之后。我想清楚了我到底要的是什么,于是我开始动手,制作了这个看起来和 Flame 并无二致的小工具:**性能更高**、**数据更透明**、**使用起来更简单** 的书签导航工具。 ![Flare 的 “First Look”](https://attachment.soulteary.com/2022/02/23/flare-webui.jpg) 在介绍如何使用它之前,我相信你可能更好奇,它好在哪里? ## Flare 的优势 Flare 最大的优势是在拥有和 Flame 一样的美观界面的前提下,拥有着绝对的性能优势:不论是 10M 不到的容器镜像体积、还是平时运行起来30M 以内的内存消耗、亦或者 99% 情况下的页面秒开(成千上万条书签),并且不会触发笔记本等设备的风扇狂转。 ![小巧的身材](https://attachment.soulteary.com/2022/02/23/docker-image-size.jpg) “快”作为 Flare 的主要优势而言,程序前端部分自然是需要一些“满分”来凑个热闹的。 ![和良好用户体验关系占比很高的前端性能测试结果](https://attachment.soulteary.com/2022/02/23/lighthouse.jpg) 这里举两个直观的小例子:使用测试工具针对不做任何配置项调整的 Flare 进行百万次请求的压力(稳定性)测试,在保持每秒 4800~5000 的并发请求的情况下,你依旧可以在1~2毫秒内打开页面,并正常使用它(极限状况下,内存使用量在 60M,通常会稳定在 30M 左右);以及 Flare 甚至是可以跑在一台搭载 2015 年 S805 芯片的ARM盒子上(成本差不多 50 元)。 ```bash # 简单的压力测试示例 wrk -t16 -c 100 -d 300s http://localhost:5005/ Running 5m test @ http://localhost:5005/ 16 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 29.09ms 33.99ms 619.31ms 85.99% Req/Sec 302.64 84.43 710.00 69.26% 1446450 requests in 5.00m, 33.70GB read Requests/sec: 4819.96 Transfer/sec: 114.99MB ``` 除了“天下武功,唯快不破”之外,Flare 拥有更简单透明的数据策略,使用文本格式来存储书签,不论是在遥远的未来,程序在当前的硬件设备和操作系统上无法运行的时候,我们遇到不得不切换软件的情况;还是在你使用 Flare 的过程中,发现了更符合你自己的审美的工具,你都可以以极低成本来进行数据迁移。“**用户的数据,应该用户自己做主**”,至少我是这样认为的。 大家对于美的要求一定是不同的,但如果我们使用的书签图标的风格和品质是高度一致的,那么软件的界面还是“比较能打,并且能打好长一阵的”(个人使用软件界面的底线,至少得是耐看)。这里我寻找和定制了几十个简约的天气动画图标,以及将 6000 多个 Material Design Icons 集成在了软件里,方便大家“开箱可用”。关于图标的使用细节,可以参考[这篇文档](https://github.com/soulteary/docker-flare/blob/main/docs/material-design-icons.md)。 ![内置了一个懒人必备的图标快速选择工具](https://attachment.soulteary.com/2022/02/23/icon-cheat-sheets.jpg) 在常用的天气展示功能上,相比较 Flame,Flare 的使用成本也更低。通常情况下你只需要启动软件,程序便会以非常克制的频率去获取必要的天气数据,并且尽可能让你少去设置(感谢 IPIP.net 提供的地理位置接口)。**此处是目前 Flare 唯一需要联网的功能**,你可以通过启用“离线模式”来禁止 Flare 联网,或者参考这个 [Issue 回复](https://github.com/soulteary/docker-flare/issues/4#issuecomment-1041178633),完成对容器应用的完全的、彻底的网络禁用操作,从根本上解决隐私顾虑。最新的版本里,程序也支持了使用外部的图片地址,或者让程序直接从目标链接网站抓取图标,来让页面中链接区分度更明显。 当然,为了照顾一些小伙伴随时随地的编辑需求,最近的版本更新中,也添加了在线编辑的功能。 ![内置了一个简单的 Excel 风格编辑器](https://attachment.soulteary.com/2022/02/23/editor.jpg) 接下来,我们来看看如何使用它。当然,除了上面这些内容之外,还有一些很小的细节,就留给好奇的你来探索啦! ## 快速初始化 Docker 环境 目前 Flare 的下载和安全都需要使用 Docker 来完成,如果你是 Mac 或 Windows 用户,可以通过下载安装桌面版的 Docker 完成基础运行环境的初始化。 如果你是一个 Linux 初学者,可以考虑使用我做的一个简单的脚本,用来快速的安装和初始化 Docker 和常用工具 `docker-compose`。如果你的服务器在海外,可以使用下面的命令,快速完成环境的安装: ```bash curl -sL https://github.com/soulteary/Home-Network-Note/raw/master/scripts/install-docker.sh | bash curl -sL https://github.com/soulteary/Home-Network-Note/raw/master/scripts/install-compose.sh | bash ``` 如果你的环境在国内,则可以执行下面的命令,并根据日志输出的提示,完成环境的安装: ```bash curl -sL https://github.com/soulteary/Home-Network-Note/raw/master/scripts/install-docker-cn.sh | bash curl -sL https://github.com/soulteary/Home-Network-Note/raw/master/scripts/install-compose-cn.sh | bash ``` 上面的安装脚本,我上传到了 GitHub 中,有需要的小伙伴可以自取:[https://github.com/soulteary/Home-Network-Note/tree/master/scripts](https://github.com/soulteary/Home-Network-Note/tree/master/scripts) 。 ## 快速安装和使用 Flare Flare 的使用方式有很多,不过为了“可持续发展”,我会将常用的方式都讲解一遍。 先来聊聊最简单的方案。(来自作者的小提醒,以下方案,根据个人情况选择一种顺手的即可) ### HelloWorld:使用 Docker 快速试用 Flare 在 Docker 环境就绪之后,我们可以通过一条简单的命令,来完成 Flare 的启动: ```bash docker run --rm -it -p 5005:5005 -v `pwd`/app:/app soulteary/flare ``` 当命令执行完毕,我们将能看到类似下面的日志输出: ```bash INFO[2022-02-23T19:08:43+08:00] Flare v0.3.1-85EED66 linux/amd64 BuildDate=2022-02-23T10:22:43+0800 INFO[2022-02-23T19:08:43+08:00] INFO[2022-02-23T19:08:43+08:00] 程序服务端口 5005 INFO[2022-02-23T19:08:43+08:00] 页面请求合并 false INFO[2022-02-23T19:08:43+08:00] 启用离线模式 false INFO[2022-02-23T19:08:43+08:00] 已禁用登录模式,用户可直接调整应用设置。 INFO[2022-02-23T19:08:43+08:00] 在线编辑模块启用,可以访问 /editor 来获取程序使用帮助。 INFO[2022-02-23T19:08:43+08:00] 向导模块启用,可以访问 /guide 来获取程序使用帮助。 INFO[2022-02-23T19:08:43+08:00] 程序已启动完毕 🚀 ``` 这个时候,我们在浏览器中打开 `http://localhost:5005`,就能够看到前文中的书签导航页面了。 我们查看执行上面命令所在目录,会发现文件夹中“多出了”几个文件: ```bash app ├── apps.yml ├── bookmarks.yml └── config.yml ``` 这些文件就是存储着“应用书签”、“分类书签”以及“程序配置”的数据文件啦,除了 `config.yml` 可以随意删除丢弃之外,其他两个文件中保存着你的书签数据,请注意妥善保存和备份。 我们随便打开一个书签数据文件,将能够看到类似下面的内容: ```yaml links: - name: 示例链接 link: https://link.example.com icon: evernote desc: 链接描述文本 - name: 示例链接 link: https://link.example.com icon: FireHydrant desc: 链接描述文本 - name: 示例链接 link: https://link.example.com icon: email desc: 链接描述文本 ... ``` 没错,flare 中的链接就是以这样的格式保存起来的,一个个简单的“文本文件”,你可以使用任何你喜欢的方式对它进行编辑,以及任何你喜欢的方式对这些数据进行保存。当你根据自己的需求修改完这个文件,在刷新浏览器页面后,Flare 中的内容也会同步更新。 如果你希望软件能够以后台方式运行,或者希望软件能够换个端口运行,比如监听到 `8080`,可以将运行参数修改为: ```bash docker run --rm -d -p 8080:5005 -v `pwd`/app:/app soulteary/flare ``` ### 使用 docker-compose 运行 Flare 相比较使用一次性的命令,使用 `docker-compose` 可以让我们基于明确的配置文件来运行容器应用(比如 flare ),并细粒度的设置应用的功能,而无需记忆各种麻烦的参数,下面是一个简单的示例。 ```yaml version: '3.6' services: flare: image: soulteary/flare restart: always command: flare ports: - 5005:5005 volumes: - ./app:/app ``` 上面的配置只用了十行左右的代码,就完成了指定 flare 容器镜像、flare 启动命令、开放端口、映射数据文件,以及进程守护,遇到问题自动重启恢复,是不是有“真香”的味道。 当然,为了小伙伴更好的使用,我一般会为 `docker-compose` 配置文件加上一些必要的注释: ```yaml version: '3.6' services: flare: image: soulteary/flare restart: always # 默认无需添加任何参数,如有特殊需求 # 可阅读文档 https://github.com/soulteary/docker-flare/blob/main/docs/advanced-startup.md command: flare # 启用账号登录模式 # command: flare --nologin=0 # environment: # 如需开启用户登录模式,需要先设置 `nologin` 启动参数为 `0` # 如开启 `nologin`,未设置 FLARE_USER,则默认用户为 `flare` # - FLARE_USER=flare # 指定你自己的账号密码,如未设置 `FLARE_USER`,则会默认生成密码并展示在应用启动日志中 # - FLARE_PASS=your_password # 是否开启“使用向导”,访问 `/guide` # - FLARE_GUIDE=1 ports: - 5005:5005 volumes: - ./app:/app ``` 我们将上面的文件保存为 `docker-compose.yml`,然后使用 `docker-compose up -d`,稍等片刻,还是使用浏览器访问 `http://localhost:5005`,不出意外,你将看到 flare 的简洁的界面。 ### 搭配 Traefik 使用 Flare 我的老读者中有不少小伙伴是 Traefik 用户,所以这里也给出 Traefik 的容器编排配置。 如果你有使用 `docker-compose`、`nginx` 的经验,那么我推荐你可以试试 Traefik,在熟悉之后,你将打开一个新的世界。如果你还没有玩过它,可以参考这个项目,来快速上手:[https://github.com/soulteary/traefik-example/](https://github.com/soulteary/traefik-example/),或者阅读我以往的包含 [Traefik 使用的技术文章](https://soulteary.com/tags/traefik.html)。 ```yaml # Traefik 快速上手和使用,可参考 https://github.com/soulteary/traefik-example/ version: '3.6' services: flare: image: soulteary/flare restart: always # 默认无需添加任何参数,如有特殊需求 # 可阅读文档 https://github.com/soulteary/docker-flare/blob/main/docs/advanced-startup.md command: flare labels: - "traefik.enable=true" - "traefik.docker.network=traefik" - "traefik.http.routers.traefik-flare-http.middlewares=https-redirect@file" - "traefik.http.routers.traefik-flare-http.entrypoints=http" - "traefik.http.routers.traefik-flare-http.rule=Host(`flare.example.com`)" - "traefik.http.routers.traefik-flare-http.service=dashboard@internal" - "traefik.http.routers.traefik-flare-https.entrypoints=https" - "traefik.http.routers.traefik-flare-https.rule=Host(`flare.example.com`) && PathPrefix(`/`)" - "traefik.http.routers.traefik-flare-https.tls=true" - "traefik.http.services.traefik-flare-backend.loadbalancer.server.scheme=http" - "traefik.http.services.traefik-flare-backend.loadbalancer.server.port=5005" networks: - traefik expose: - 5005 volumes: - ./app:/app networks: traefik: external: true ``` 使用方式依旧是简单的 `docker-compose up -d`,在容器运行起来之后,浏览器直接访问我们在 Traefik 中动态注册的域名即可,本例子中是 `flare.example.com`。 虽然说了这么多种安装方式。 但是,我猜此刻的你对 Flare 还是会感到迷茫,接下来,我们来更进一步的了解 Flare 的功能和界面。 ## 进一步了解 Flare 考虑到使用文本介绍会占用比较多的篇幅,于是我做了一个简单的使用向导,大概只需要十几秒时间,就能够快速看完功能点的介绍。 那么,如何打开 Flare 的向导呢?只需要在原来的地址栏后面加上 `/guide` 即可,像是这样:`http://localhost:5005/guide`,是不是很简单。 ![Flare 的向导小工具](https://attachment.soulteary.com/2022/02/17/flare-guide.jpg) 接下来,聊聊扩展话题。 ## 在公网服务器上使用 Flare 虽然默认情况下 Flare 是单机模式运行,不需要“用户登录”。但是有的小伙伴希望软件能够跑在云服务器上,比如让吃灰久矣的“轻量云”焕发生机。 这个时候,如果谁都能够修改应用设置,未免会造成许多麻烦。所以我们可以调整一下程序的自定义启动参数,让程序禁用“免登录模式”。 ```bash flare --disable_login=0 ``` 默认情况下,程序会使用 `flare` 的账户名称,和随机生成的管理密码,如果我们想使用自己的指定账号和密码登录的话,可以通过在环境变量中设置 `FLARE_USER` 和 `FLARE_PASS` 两个家伙,来替换 flare 的默认登录账号和随机密码,以 `docker-compose` 编配文件为例: ```yaml version: '3.6' services: flare: command: flare --disable_login=0 ... ``` 是不是很简单?完整的配置可以参考下面的内容: ```yaml version: '3.6' services: flare: image: soulteary/flare:0.2.7 restart: always # 默认无需添加任何参数,如有特殊需求 # 可阅读文档 https://github.com/soulteary/docker-flare/blob/main/docs/advanced-startup.md # 启用账号登录模式 command: flare --disable_login=0 environment: # 如需开启用户登录模式,需要先设置 `nologin` 启动参数为 `0` # 如开启 `nologin`,未设置 FLARE_USER,则默认用户为 `flare` - FLARE_USER=flare # 指定你自己的账号密码,如未设置 `FLARE_USER`,则会默认生成密码并展示在应用启动日志中 - FLARE_PASS=your_password ports: - 5005:5005 volumes: - ./app:/app ``` 当你使用 `docker-compose up -d` 启动应用之后,使用 `docker-compose ps`,我们就可以看到包含密码的日志输出啦: ```bash INFO[2022-02-23T19:10:07+08:00] Flare v0.3.1-85EED66 linux/amd64 BuildDate=2022-02-23T10:22:43+0800 INFO[2022-02-23T19:10:07+08:00] INFO[2022-02-23T19:10:07+08:00] 程序服务端口 5005 INFO[2022-02-23T19:10:07+08:00] 页面请求合并 false INFO[2022-02-23T19:10:07+08:00] 启用离线模式 false INFO[2022-02-23T19:10:07+08:00] 启用登录模式,调整应用设置需要先进行登录。 INFO[2022-02-23T19:10:07+08:00] 当前内容整体可见性为: DEFAULT INFO[2022-02-23T19:10:07+08:00] 用户未指定 `FLARE_USER`,使用默认用户名 flare INFO[2022-02-23T19:10:07+08:00] 用户未指定 `FLARE_PASS`,自动生成应用密码 dd0624b7 INFO[2022-02-23T19:10:07+08:00] 在线编辑模块启用,可以访问 /editor 来获取程序使用帮助。 INFO[2022-02-23T19:10:07+08:00] 向导模块启用,可以访问 /guide 来获取程序使用帮助。 INFO[2022-02-23T19:10:07+08:00] 程序已启动完毕 🚀 ``` 接下来是登录应用和进行具体设置,这里就不过多赘述了,留给你自己探索和把玩啦。 如果你有更私密的要求,还可以使用 `flare --disable_login=0 --visibility=private` 设置首页内容必须登录能够看到。 ## 其他资料 如果你对 Flare 的制作过程感兴趣,可以移步 [《Flare 制作记录:应用前后端性能优化》](https://soulteary.com/2022/01/19/flare-production-record-application-frontend-and-backend-performance-optimization.html) 这篇文章,分享了不少优化的思路和细节。 除此之外,为了方便你使用和调整 Flare,还可以参考下面的文档: - [《Flare - 自定义启动参数》](https://github.com/soulteary/docker-flare/blob/main/docs/advanced-startup.md) - [《关闭免登录模式后,如何设置用户账号》](https://github.com/soulteary/docker-flare/blob/main/docs/application-account.md) - [《如何挑选和使用图标》](https://github.com/soulteary/docker-flare/blob/main/docs/material-design-icons.md) - [《如何和 Traefik 一起使用》](https://github.com/soulteary/traefik-example) ## 最后 如果你觉得这个项目有帮到你,欢迎对本文进行点赞转发,让其他的小伙伴也能看到它(用户反馈越多,更新越快)。 如果你是一个代码爱好者,还可以在 GitHub 中为项目点赞✨(star)给予制作人一个小小的鼓励;如果你希望收到这个项目的更新推送,建议点击 GitHub 项目中的关注 👀(watch)并选择适合自己的关注模式,推荐选择 release 模式,一旦有新版出现,你会第一时间得到推送提醒。 当然,非常欢迎你在我主要出没的地方进行留言反馈,一起改进 Flare 的体验。 --EOF