飞牛 NAS 部署 Part-DB 踩坑实录:镜像拉不动、数据库还会消失

家里的螺丝、钉子、扎带一直散在好几个盒子里,想找一颗 M3×8 全靠翻。之前用 HomeBox 记物品,但它什么都管、什么都不细,螺丝这种” 还剩 300 颗” 的库存它记不了。调研了一圈,选了 Part-DB:分类、自定义参数(直径、长度、牙距、材质)、存储位置,正好对上五金件的管理方式。

部署本身很简单。飞牛 NAS 上照惯例建一个 compose 目录,把镜像、卷、端口写进去,再加几行 WatchCow 标签让桌面出图标。五分钟的事。

然后坑就来了,一共四个,一个比一个深。

坑一:镜像拉不动

docker compose up 下去,报错:Get "https://registry-1.docker.io/v2/": EOF。

这台 NAS 的 daemon.json 里配了六个镜像加速源,全军覆没:daocloud 和飞牛官方镜像站有白名单,不含 partdborg;剩下几个公开加速站要么超时要么挂死。奇怪的是,同样这些域名,curl 测试是通的。

排查了半天,真凶是 IPv6。NAS 解析域名只拿到 IPv6 地址,走 Cloudflare 的时候小请求正常、大流量卡死,典型的 MTU / GFW 问题。docker 拉镜像流量大,全卡在传输半路;curl 只发小请求,所以看起来” 通”。

修法:在 /etc/hosts 里把加速域名钉到一个能连通的 IPv4 上。注意同一个域名的两个 CF 任播 IP,一个通一个不通,钉之前先 curl -4 测一下。之后拉镜像就顺了,355MB 一口气拉完。

坑二:网页打不开,一直跳转

容器起来了,健康检查也过了,浏览器打开却是个 308 重定向:HTTP 请求被强制跳到 HTTPS,然后打不开。

Part-DB v2 换成了 FrankenPHP + Caddy 架构,Caddy 的默认站点是 localhost,其他 Host 的请求一律 308 到 HTTPS。内网 HTTP 直连的场景下这就没法用。

解法是一行环境变量:SERVER_NAME=:80。Caddy 就只监听 HTTP 端口,不再做 HTTPS 跳转。

坑三:数据库凭空消失,密码天天变

这是最坑的一个。

折腾完上面两个,把初始 admin 密码抄下来去登录,提示用户名或密码错误。上机器一查,用户表里明明躺着 admin 用户。拿数据库里的 hash 一比对,密码确实对不上。

原来 v2 镜像的项目根目录是 /app,而官方文档还写着老架构的 /var/www/html。卷挂到了应用根本不用的路径,SQLite 数据库就落在容器可写层里。每次容器重建,数据库归零,迁移脚本重新跑,admin 密码重新生成。容器每重建一次,之前的密码就作废一次。

症状就是” 登录突然失效”。修法是把卷路径改成 /app/uploads 和 /app/public/media,改完用 ls 确认 app.db 真的出现在宿主机磁盘上,才算持久化成功。

坑四:甩不掉的警告横幅

登录进去之后,管理员首页挂着一条黄色横幅:TRUSTED_HOSTS 未配置,有 Host 头注入风险。

照着提示在 compose 里加一行 TRUSTED_HOSTS 正则就行。有个细节:这个值在 YAML 里不能加引号,加了引号会变成值的一部分。配好之后我拿伪造 Host 头测了一下,正常访问正常响应,伪造 Host 直接 400,横幅消失。

总结

问题根因修复
镜像拉不动镜像源白名单 + IPv6 大流量卡死/etc/hosts 钉可用 IPv4
网页 308 跳转Caddy 默认强制 HTTPSSERVER_NAME=
登录密码失效卷路径挂错,数据库不落盘卷改成 /app 路径
警告横幅TRUSTED_HOSTS 未设compose 加正则,不加引号

Part-DB 本身是个好东西,参数化筛选用起来顺手。装它的过程也值回票价:四个坑里三个是文档滞后或者网络环境问题,全靠日志和 ls 一点点翻出来。

有些工具装十分钟,修两小时。但修完那两小时,它才真正变成你的工具。