这是「Docker 好项目」系列的第 15 期。第 12 期装了 Miniflux,解决的是"新内容主动送上门"——RSS 订阅的是持续更新的站点。但还有另一类东西:一篇值得回访的教程、一个想用的开源项目、某天刷到的报价页面。它们不值得订阅,但丢进浏览器的收藏夹,换台电脑就没了,搜也只能搜标题。这一期补的就是这一环。

痛点开场
先盘点一下浏览器收藏夹的死法:
- 锁死在一台设备上。Chrome 同步要登录谷歌账号,国内网络环境下这件事本身就是个坑;换浏览器(Chrome → Edge → Firefox)时收藏夹导出导入一轮,层级结构和顺序必乱
- 只能搜标题。你记得那篇文章讲的是"家用 NAS 硬盘选型",但收藏时的标题是《2026 年了还有人买机械盘?》——文件夹翻三遍找不到
- 链接会死。收藏的页面哪天 404 了、改版了、被删除了,你连它原来长什么样都回忆不起来
- 没法分享。想把收藏的一批链接发给同事/客户,只能一个个复制
网盘收藏、微信收藏、稍后读服务(Pocket 已经关了)各有各的坑,共同点是:数据不在你手里,服务说停就停。
linkding 的定位非常克制:一个自托管的书签管理器,极简、快、五分钟部署完。名字来自 link(链接)+ Ding(德语"东西")——"链接小玩意"。11k+ stars,MIT 协议,一个 Django 应用加一个 SQLite 文件就能跑,是同类里部署负担最小的一个。
能力边界
能干什么
- 书签管理:标签、批量编辑、Markdown 备注、"稍后读"(unread 状态)、归档
- 自动补全元数据:存链接时自动抓标题、描述、favicon、预览图
- 全文搜索:标题、描述、备注、URL 都能搜,支持布尔语法(
#标签 and 关键词 not #已读),大小写不敏感(SQLite 加载了 ICU 扩展来做这件事,中文搜索没问题) - 网页快照(plus 镜像):服务端用 headless Chromium 把页面存成单个 HTML 文件,链接死了也能看原文
- Internet Archive 快照(可选后台任务):自动把书签提交到 Wayback Machine 留档
- 浏览器扩展:Firefox / Chrome 官方扩展 + bookmarklet,存书签不用离开当前页面
- REST API:完整 API,设置页一键生成 Token;社区有 iOS/macOS 客户端
- RSS 输出:
/feeds/<key>/unread之类的地址可以把"未读书签"变成 RSS 源——接上第 12 期的 Miniflux,收藏夹也能当订阅源用 - 自动打标签:按 URL 规则自动加标签(比如
youtube.com video) - 导入导出:Netscape HTML 格式,所有浏览器都认,随时进得来出得去
- 多用户:支持 OIDC 单点登录和反代认证(Authelia 等),也能把书签公开分享
不干什么
- 不做全文网页检索。它搜的是你写的标题/备注/URL,不是网页正文(plus 的快照也只是存档,正文搜索不在功能范围)
- 不是稍后读工具的完全替代。它没有阅读进度、高亮标注这些功能——存、搜、读,到此为止
- 不做同步盘。它管的是"链接",不是文件本身(PDF 快照除外)
- 没有内置告警。它不是监控工具,挂了它自己不会喊——这个老规矩还是交给第 1 期 Uptime Kuma
一句话:linkding 是你的第二个大脑入口,不是你的知识库本身。想存正文并检索正文的,出门左转第 14 期 Paperless-ngx。
部署前准备
- 一台能跑 Docker 的机器。官方镜像支持 amd64 / arm64 / armv7,树莓派都能跑。默认镜像内存占用极小,2 核 2G 的机器随便跑;如果你要上 plus 镜像(网页快照),官方要求至少 1 GB 额外内存给 Chromium
- 想好数据放哪。所有数据(数据库、图标、快照)都在一个
data目录里,挂出来就行,不挑存储 - 规划域名,比如
bk.你的域名.com。可选,但强烈建议——浏览器扩展、API、多设备访问都依赖一个固定的对外地址 - 镜像。官方同时发布到 Docker Hub(
sissbruecker/linkding)和 GitHub Container Registry(ghcr.io/sissbruecker/linkding),国内拉不动一个换另一个。
关于 tag,这期我实测了一遍(v1.47.0,2026-09-13 发布):
| tag | 结果 |
|---|---|
1 |
404,不存在 |
1.47 |
404,不存在 |
1.47.0 |
200 |
latest |
200,与 1.47.0 digest 相同(sha256:e35cb50e…) |
1.47.0-plus |
200(digest 不同,是另一份镜像) |
1.47.0-alpine |
200(实验性) |
它的 CI(.github/workflows/build.yaml)只发布完整版本号 + latest + 各变体,不滚动次版本 tag——跟第 8 期 Navidrome、第 12 期 Miniflux 一类,必须钉全量版本 1.47.0。别想当然写 :1.47,那个 tag 不存在,docker pull 直接报错。
变体怎么选:
| 变体 | 适合 |
|---|---|
1.47.0(默认) |
只管存链接、搜链接。镜像小、内存省 |
1.47.0-plus |
想要服务端网页快照(Chromium + single-file-cli + uBlock 内置)。镜像大 1 GB+,运行时至少多要 1 GB 内存 |
1.47.0-alpine |
官方标注 🧪 实验性,生产别碰 |
建议先装默认版跑顺了,确实需要"存网页尸体"再换 plus——两个变体的数据目录格式一致,直接换镜像重启即可迁移。
docker run 一行版
这期是真正的"一行"——单容器、无外部依赖、SQLite 落盘:
mkdir -p /opt/linkding/data
docker run -d \
--name linkding \
-p 127.0.0.1:9090:9090 \
-v /opt/linkding/data:/etc/linkding/data \
-e TZ=Asia/Shanghai \
-e LD_SUPERUSER_NAME=admin \
-e LD_SUPERUSER_PASSWORD=换成你自己的强密码 \
--restart unless-stopped \
sissbruecker/linkding:1.47.0
几个必须知道的点:
-v …:/etc/linkding/data是唯一要挂的卷。数据库db.sqlite3、密钥secretkey.txt、图标favicons/、快照assets/、任务队列tasks.sqlite3全在里面。这个目录丢了 = 全部书签没了- 端口映射成
127.0.0.1:9090是留给反向代理的姿势;没有反代、纯内网用的话直接写-p 9090:9090 LD_SUPERUSER_NAME+LD_SUPERUSER_PASSWORD一起设,首次启动自动建管理员。官方镜像默认不带任何用户,两个变量缺一个:只写用户名不写密码时,会建出一个没有可用密码的账号(这是为反代认证准备的场景),登录页是进不去的- 密钥不用你管。首次启动时
bootstrap.sh会自动生成secretkey.txt存进 data 目录——比第 14 期 Paperless-ngx 那个必填的SECRET_KEY省心 - 容器健康检查镜像里自带(
curl http://localhost:9090/health,30 秒一次),1Panel 的容器页能直接看到 healthy
docker-compose 推荐版
services:
linkding:
image: sissbruecker/linkding:1.47.0
container_name: linkding
restart: unless-stopped
ports:
- "127.0.0.1:9090:9090" # 只绑本机,交给反向代理对外
volumes:
- ./data:/etc/linkding/data # 所有数据都在这里,备份就备它
environment:
TZ: Asia/Shanghai
# 首次启动自动建管理员(两个都设才会带密码创建)
LD_SUPERUSER_NAME: admin
LD_SUPERUSER_PASSWORD: 换成你自己的强密码
# 用了域名 + 反代就写上,否则登录时 CSRF 403
LD_CSRF_TRUSTED_ORIGINS: https://bk.你的域名.com
就这么多——没有数据库容器、没有 broker、没有缓存,这是它跟 Immich、Paperless-ngx 那种"全家桶"最大的区别。个人规模的收藏量(几千到几万条)SQLite 绰绰有余。
真要用 Postgres 的话,加一段:
db:
image: postgres:18
container_name: linkding-db
restart: unless-stopped
environment:
POSTGRES_DB: linkding
POSTGRES_USER: linkding
POSTGRES_PASSWORD: 换成你自己的强密码
volumes:
# ⚠️ postgres:18 起数据目录是 /var/lib/postgresql(不是 /data)
- pgdata:/var/lib/postgresql
# linkding 服务里追加:
# LD_DB_ENGINE: postgres
# LD_DB_HOST: db
# LD_DB_DATABASE: linkding
# LD_DB_USER: linkding
# LD_DB_PASSWORD: 换成你自己的强密码
volumes:
pgdata:
什么时候才值得上 Postgres:多人共用、数据量上万、或者你有现成的 Postgres 实例想统一备份。个人用,SQLite 是更省心的选择——备份就是一个文件的事。
配置项逐项解释
下面的默认值全部来自 v1.47.0 源码 bookmarks/settings/base.py 实测:
| 变量 | 默认值 | 说明 / 为什么这么写 |
|---|---|---|
LD_SUPERUSER_NAME |
无 | 首次启动自动建超管的用户名。用户已存在时不做任何事(不会覆盖密码) |
LD_SUPERUSER_PASSWORD |
无 | 配套密码。不设则建出的账号没有可用密码,只能走反代/OIDC 登录 |
TZ |
UTC |
Django 的 TIME_ZONE 直接读它。不改的话"按添加时间排序"看着差 8 小时 |
LD_CSRF_TRUSTED_ORIGINS |
空 | 过反代必配。格式必须带协议、不带路径:https://bk.example.com。不配的症状:页面能开,一登录 403 |
LD_USE_X_FORWARDED_HOST |
false |
信任反代的 X-Forwarded-Host。Nginx 重写 Host 头时配合使用 |
LD_LOG_X_FORWARDED_FOR |
false |
日志里记录真实客户端 IP。想接 fail2ban 就开 |
LD_DB_ENGINE |
sqlite |
postgres 才会启用下面那组 LD_DB_* 变量 |
LD_REQUEST_TIMEOUT |
60 |
uwsgi 请求超时(秒)。导入超大书签文件时调大 |
LD_REQUEST_MAX_CONTENT_LENGTH |
不限 | POST 体积上限(字节)。公网暴露时可以设个值防滥用 |
LD_DISABLE_BACKGROUND_TASKS |
false |
关掉后台任务(Wayback 快照提交等)。国内服务器建议 True,原因见踩坑清单 |
LD_SUPERVISOR_MANAGED |
false |
实验特性:supervisor 同时管 web 和后台任务,任务日志改打容器 stdout。默认模式下任务日志写在容器内的 background_tasks.log(见踩坑) |
LD_ALLOWED_INTERNAL_HOSTS |
空 | SSRF 防护白名单。默认禁止抓取内网地址(192.168.x.x、nas.local 等)的元数据/预览图。收藏内网服务就把它加白:192.168.31.0/24 |
LD_DISABLE_URL_VALIDATION |
false |
关掉 URL 校验。带下划线的域名、chrome:// 这类协议会被默认校验拒收 |
LD_SESSION_COOKIE_AGE |
1209600 |
登录会话时长(秒)= 14 天。嫌老要重新登录就调大 |
LD_FAVICON_PROVIDER |
Google 服务 | 默认 t1.gstatic.com 的 favicon 接口,国内服务器不可达。可换成 DuckDuckGo(同样要出网)或自建服务,详见踩坑清单 |
LD_ENABLE_REFRESH_FAVICONS |
true |
是否允许刷新图标。图标拉不到的机器直接关,省得后台任务反复失败 |
LD_ENABLE_SNAPSHOTS |
false(plus 镜像内置 true) |
服务端网页快照。只有 plus 镜像里有单文件工具,默认镜像设了也没用 |
LD_SINGLEFILE_TIMEOUT_SEC |
120(源码值;官方文档页面还写着 60) |
单次快照超时。弱网/大页面调大 |
LD_SNAPSHOT_PDF_MAX_SIZE |
15 MB | 快照转 PDF 的体积上限 |
LD_CORS_ALLOWED_ORIGINS |
空 | 允许浏览器跨域调 API 的来源。自建前端才需要 |
LD_CONTEXT_PATH |
空 | 子路径部署(如 example.com/linkding/),值必须以 / 结尾 |
LD_SERVER_PORT |
9090 |
容器内监听端口,一般不动 |
1Panel 面板怎么搞
好消息:1Panel 应用商店里有 linkding(264 个应用里命中 linkding,分类"实用工具")。我核对了商店的编排文件,几个关键信息:
- 商店版本是
1.47.0-plus(最新版,直接带网页快照功能) - 默认端口 9090,挂载
./data:/etc/linkding/data - 表单里有管理员用户名/密码两项(默认值是
admin/passwd_1Panel——装之前务必改掉密码,这个默认值全网都知道)
商店安装路线:
- 1Panel 左侧 应用商店 → 搜
linkding→ 安装 - 端口保持 9090(被占用就换一个),用户名密码改成你自己的
- 装完它挂在
1panel-network网络里,容器名就是应用名
不想用商店(想用更省内存的默认镜像)就走 容器 → 编排,把上面那份 compose 贴进去。两种方式二选一,别同一个数据目录装两份,SQLite 文件被两个容器同时写是会损坏的。
两个 1Panel 实操提示:
- 商店版是 plus 镜像,2G 内存的小机器上开快照功能要悠着点——Chromium 跑一次快照能吃掉几百 MB。可以在应用参数里不动它,但把 profile 设置里的快照选项关掉,等需要时再开
- 反向代理用 1Panel 的 网站 → 反向代理 建,目标
http://127.0.0.1:9090,顺手申请 Let's Encrypt 证书
首次访问
- 确认容器健康:
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9090/health
# 200
- 浏览器打开
https://bk.你的域名.com,用你设的管理员账号登录。compose 里没设LD_SUPERUSER_*的话,手动建一个:
docker exec -it linkding python manage.py createsuperuser --username=admin --email=you@example.com
# 会提示输密码
- 登录后长这样——左边是书签列表(标题、备注、标签、操作),右边是标签云,顶部搜索框支持布尔语法:

- 第一件事去 Settings → Integrations 页把 REST API Token 复制出来存好——浏览器扩展、手机 App、第 12 期的联动全靠它
- 装浏览器扩展:Firefox / Chrome 商店搜 "linkding extension",填服务地址 + Token,之后在任何页面点一下就能存书签
- 把老收藏搬进来:浏览器先导出 HTML(Chrome/Edge:书签管理器 → 导出书签),再在 linkding 的 Settings → General → Import 里选文件导入。去重是自动的(v1.46 起修复了导入不去重的问题),放心整包导入
最小可用配置
"能跑"和"顺手"之间,就差这几步。
1)定好搜索习惯,标签少而准。linkding 的搜索语法值得花两分钟学会(官方文档 search 页全文):
docker 自托管 #教程 → 标题/备注含 docker、自托管,且带"教程"标签
#已读 not #归档 → 两个标签做差集
"把书签搬回自己服务器" → 精确短语
(#工具 or #教程) docker → 括号分组
经验:标签标"类型"(教程/工具/报价页),"状态"交给 unread 开关,别建"2026年收藏"这种时间类标签——它有按时间筛。
2)批量打标签用自动规则。Settings → Profile → Auto Tagging:
github.com 开源项目
youtube.com video
mp.weixin.qq.com 公众号
存链接时自动带上,比事后补标签省太多事。
3)国内服务器的 favicon 问题(重要)。默认图标源是 t1.gstatic.com(Google 家的),华为云国内机器拉不到,表现为:书签能存,图标永远空白,后台任务反复报错。三个选择:
# 方案 A:换 DuckDuckGo 的源(同样需要能出外网,华为云默认不通)
LD_FAVICON_PROVIDER=https://icons.duckduckgo.com/ip3/{domain}.ico
# 方案 B:有代理出口的话,给容器配 HTTP 代理再走默认源
# HTTP_PROXY=http://你的代理:7890
# 方案 C:干脆关掉自动刷新图标(profile 设置里也能关)
LD_ENABLE_REFRESH_FAVICONS=False
图标不影响搜索和链接本身,个人建议:先方案 C 用着,哪天有代理出口了再开。
4)想收藏内网服务的地址(比如 http://192.168.31.193:8099):
LD_ALLOWED_INTERNAL_HOSTS=192.168.31.0/24
不设的话 linkding 会拒绝为内网 URL 抓元数据——这是它的 SSRF 防护,不是 bug。
5)把"稍后读"用起来。存书签时勾 unread,列表里就有"未读"视图;读完点一下归档。这套流程比文件夹方案轻得多——收藏夹的熵增,靠状态字段解决,不靠建文件夹。
告警 / 通知配置
linkding 不是监控类工具,这节说三件事:它挂了谁告诉你、新收藏怎么送到眼前、链接死了谁兜底。
1)存活监控 → Uptime Kuma(第 1 期)
加一个 HTTP 监控,URL 填 https://bk.你的域名.com/health,期望状态码 200。这个端点无需登录(容器健康检查也在用它),是最干净的判据。告警通道的老规矩不再重复:别把监控告警和被监控服务放同一条链路上。
2)"新收藏"输出 → RSS 喂给 Miniflux(第 12 期)
linkding 每个用户自带三条 RSS 源(源码 bookmarks/urls.py 实测):
/feeds/<feed_key>/all 全部书签
/feeds/<feed_key>/unread 未读书签
/feeds/<feed_key>/shared 分享的书签
feed_key 在 Settings → Integrations 页能看到。把这个地址填进 Miniflux 的订阅里,"我在别处存了个书签"就会出现在你的 RSS 阅读流里——两个自托管服务就这么咬合上了。
3)Internet Archive 快照 —— 国内机器直接关
书签支持自动提交到 web.archive.org 留档(后台任务),想法很好,但 archive.org 在国内不可达,华为云国内机器上这个任务会反复失败刷日志。直接:
LD_DISABLE_BACKGROUND_TASKS=True
想给重要链接留"尸体",用 plus 镜像的本地快照替代——HTML 文件落在你自己的 data/assets/ 里,不依赖任何外网服务。
反向代理与 HTTPS
以 Nginx Proxy Manager(第 2 期)为例:
- Forward Hostname:
127.0.0.1,Port:9090,Schemehttp - 勾 SSL,申请 Let's Encrypt 证书
NPM 默认会透传 Host 头,一般直接能登录。如果遇到 403 CSRF verification failed(官方 troubleshooting 页的第一条就是它),按顺序排查:
- compose 里补上
LD_CSRF_TRUSTED_ORIGINS: https://bk.你的域名.com(带协议、不带结尾斜杠)然后重建容器 - 自定义 Nginx 配置的场景,确认转发了真实 Host:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
- 还不行就开
LD_USE_X_FORWARDED_HOST=True,让 linkding 以反代传来的 Host 为准
Caddy 用户一行流:
bk.你的域名.com {
reverse_proxy 127.0.0.1:9090
}
安全提醒:linkding 里存的可能不只是链接,还有备注里贴的账号信息、内网地址。公网暴露时三件事必须做齐:强密码、HTTPS、(可选)定期改 API Token。真要防爆破,把 LD_LOG_X_FORWARDED_FOR=True 打开,再用第 1 期的方式监控登录失败就行——它没有内置的登录限流。
踩坑清单
:1.47这个 tag 不存在。CI 只发完整版本号,写sissbruecker/linkding:1.47会直接 pull 失败。钉1.47.0。- 升级 = 换镜像 + 原数据目录重启。
docker compose pull && docker compose up -d即可,迁移自动跑。官方有个install-linkding.sh脚本可以一键干这事。升级前顺手备份data/(见下一节)。 - 别给容器加
user:指令。bootstrap.sh每次启动都要chown -R www-data数据目录,非 root 启动会失败;uwsgi 本身会主动降权到 www-data 运行,让容器以默认 root 起即可。 - 后台任务日志默认不在
docker logs里。默认模式下 Huey 任务进程的输出写到容器内的/etc/linkding/background_tasks.log——这个路径不在 data 卷里,容器重建就没了。想在docker logs里直接看,加LD_SUPERVISOR_MANAGED=True(experimental)。 - favicon 拉不到不是坏了,是国内访问不到 Google 的图标服务(默认源)。处理见"最小可用配置"第 3 条。
LD_DISABLE_BACKGROUND_TASKS=True的附带影响:Wayback 提交、favicon 刷新这类后台活全停。国内机器这是特性不是缺陷。- URL 校验会拒收一些"看起来合法"的地址:带下划线的域名、没有顶级域名的地址、
chrome://之类的协议。确认自己要存这类链接就设LD_DISABLE_URL_VALIDATION=True。 - 导入大书签文件超时:几千条以上的 HTML 导入可能撞上 60 秒请求超时,临时加
LD_REQUEST_TIMEOUT=300,导完再去掉。 - plus 镜像快照失败常见三种:网站反爬(快照拿到的是验证页)、登录页面内容不对、超时。官方给的缓解手段是
LD_SINGLEFILE_OPTIONS=--user-agent="..."换 UA 和调大LD_SINGLEFILE_TIMEOUT_SEC。快照不是百分百可靠的,重要内容用浏览器 SingleFile 扩展手动存更稳(linkding 提供/api/bookmarks/singlefile/接口直接接)。 - SQLite 直接 cp 有风险:数据库开了 WAL 模式,
db.sqlite3+db.sqlite3-wal两个文件都要拷,或者干脆用官方的full_backup命令(下一节)。数据库正在写的时候裸拷文件,恢复时可能打不开。 - 别用
:latest:跟往期同一句话——它和完整版本号当前指向一致,但你不知道哪天它就跳到下一个 minor。 - 多容器共写一个 data 目录 = 数据损坏。1Panel 商店版和自建编排二选一,别叠着装。
备份
数据全在一个目录里,这是它对备份最大的友好:
# 官方全量备份(SQLite 场景专用,把数据库 + 图标 + 快照打包)
docker exec -it linkding python manage.py full_backup /etc/linkding/data/backup.zip
# 拷回宿主机
docker cp linkding:/etc/linkding/data/backup.zip ./linkding-backup.zip
注意 full_backup 产物本身写在 data 目录里——别把它和源数据放在同一块盘上就算完事,起码推到另一台机器(比如第 14 期那台)。
日常 cron 方案(数据目录整目录走 SQLite 在线备份 + 文件同步):
#!/usr/bin/env bash
set -euo pipefail
DATA=/opt/linkding/data
DEST=/backup/linkding/$(date +%F)
mkdir -p "$DEST"
# 1) 数据库在线备份(官方 full_backup 内部就是这么做的,事务安全)
docker exec linkding python manage.py full_backup /etc/linkding/data/backup.zip
mv "$DATA/backup.zip" "$DEST/backup.zip"
# 2) 配置和 compose 文件顺手带上
cp /opt/linkding/docker-compose.yml "$DEST/" 2>/dev/null || true
恢复:新机器起好容器(先别挂旧数据),把 backup.zip 解压成 data/ 目录,挂载重启即可。导入导出 HTML 那条路只适合救回链接本身(丢备注、丢快照关联),不能当主备份——官方备份文档里专门列了它的六条局限。
小结
适合谁
- 收藏夹超过三位数、换过浏览器/电脑、经历过"收藏夹失忆"的人
- 已经在跑 Miniflux(第 12 期)的人——RSS 管持续内容,linkding 管散装收藏,两件套刚好互补
- 想给团队/客户维护一份"常用链接清单"的(它有分享和公开只读功能)
- 树莓派/小主机党:镜像支持 arm 全家桶,默认镜像内存占用极低
- 想要"链接死了也能看原文"的:plus 镜像一步到位
不适合谁
- 想要网页正文全文检索、高亮标注的——那是 readwise/Omnivore 类工具的地盘,linkding 刻意不做
- 收藏数只有几十条、且只用一台设备的——浏览器自带收藏夹 + 定期导出就够了
- 想要多人协作共建知识库的——它的多用户是"各管各的 + 可分享",不是 Notion 那种协作
系列过半,回头看这 15 期的分工已经能拼出一张完整的自托管地图:Uptime Kuma 看门、NPM 开门、Vaultwarden 管钥匙、Immich 管照片、Navidrome 管音乐、Miniflux 管订阅、ntfy 管推送、Paperless-ngx 管纸、linkding 管链接。每个都是单点小工具,合起来是一套不打折的个人基础设施。
项目地址
- GitHub:https://github.com/sissbruecker/linkding
- 官方文档:https://linkding.link/(options 页是配置项全集,troubleshooting 页第一条就是反代 CSRF)
- 在线演示:https://demo.linkding.link/(可以先摸一遍再决定装不装)
- Docker 镜像:
sissbruecker/linkding:1.47.0(Docker Hub 与ghcr.io/sissbruecker/linkding:1.47.0同源,digest 一致;网页快照需求换:1.47.0-plus)