Docker Compose 全家桶解读
拿到 Compose 文件怎么改
Immich 官方维护了一份示例 Compose 文件,部署整个过程就是下载它、改几行、启动。文件不长,但第一次接触多服务编排的人会被五六个服务吓住,其实每个服务的角色都很单一,读完这一节你就知道哪一行必须改、哪一行可以闭眼照抄。
拿到文件后有四类东西需要你的决策:镜像版本、卷映射、环境变量、依赖关系。版本号建议跟着官方文档填当前稳定版,不要手写 latest,因为 latest 每次拉取的版本不可控,出问题没办法复现现场。卷映射是真正需要动脑的部分——它决定了照片、数据库、机器学习缓存分别落在硬盘的哪里。环境变量里最要紧的是数据库密码和时区,前者要改成复杂值,后者要和主机一致。

一条经验先摆在这里:所有卷映射规则改完、启动服务之前,自己顺着文件把目录路径在系统里建好、权限确认一遍,能避开八成启动报错。
逐服务拆解
把全家桶逐个看一遍,每个服务的职责、出问题的表现、需要配置的内容都列在下面这张表里。
| 服务 | 职责 | 主要配置 | 出问题的表现 |
|---|---|---|---|
| server | 业务逻辑与接口入口 | 数据目录卷、时区 | 页面打不开、上传失败 |
| web | 网页界面文件 | 一般无需改动 | 界面空白或样式丢失 |
| machine-learning | 人脸识别与向量化 | 模型名称、显存相关项 | 人物分组不更新、搜索失效 |
| redis | 缓存 | 一般无需改动 | 时间线加载变慢 |
| postgres | 元数据库 | 数据卷、密码 | 登录失败、启动循环 |
server 是整个系统的心脏,所有 App 和网页的请求都从这里走。它对接四个伙伴:照片存在卷里、元数据交给 postgres、频繁读取的列表走 redis 加速、智能功能调用 machine-learning。理解了这个结构,排查问题的思路就有了——现象在哪一环,就去拆哪一环的日志。
postgres 是全家桶里最不能掉以轻心的成员。照片文件丢了还能从别处找回来,数据库崩了则意味着人脸分组、相册结构、修复记录全部归零。所以它的卷映射位置、备份策略必须单独规划,不要和上传目录混在一起,更不要放在 tmp 之类的临时位置。

启动顺序与重启策略
多服务 Compose 文件里有一组 depends_on 声明,保证 postgres 和 redis 先就位、server 后启动。正常情况下你不需要改这组声明,只有在手动单独重启某个服务时才需要留意顺序——先起数据库再起业务服务,避免 server 在数据库还没起来时进入重启循环。
重启策略建议给每个服务都配上除非明确停止这种档位。家庭场景里断电、断网是常态,开机自启比人工介入可靠得多。关于开机自启与系统服务的扩展配置,可以翻《自建 NAS 完全指南》 的容器管理章节,那里有按系统整理的清单。
镜像版本:别用 latest
镜像版本这一项值得单开一节强调。latest 标签看起来永远是最新的,实际上它的含义是拉取时指向当时的最新,今天拉和明天拉可能不是同一个版本。家庭场景里这会带来两个麻烦:一次拉取拿到有问题的版本、无法回滚到之前能跑的那一版;两台机器同时部署,拉到的版本不一样,排查问题对不上。
推荐做法是把版本钉死成具体版本号,官方发行说明里每个版本都有对应标签。升级时手动改成新版本号,同时保留旧版本号作为回滚目标。这个习惯前期多花三十秒,出问题时省下的是整个晚上。
| 版本写法 | 可复现 | 可回滚 | 建议 |
|---|---|---|---|
| latest | 否 | 否 | 不推荐 |
| 具体版本号 | 是 | 是 | 推荐 |
| 版本区间 | 部分 | 部分 | 慎用 |
卷映射是部署的核心
环境变量里值得逐项看的
示例文件里有一长串环境变量,大部分保持默认即可,以下几项值得单独确认。
| 变量类别 | 作用 | 建议 |
|---|---|---|
| 数据库密码 | postgres 访问凭据 | 改成强密码,与备份脚本一致 |
| 时区 | 时间线分组依据 | 与主机一致的时区值 |
| 模型名称 | 机器学习模型选择 | 默认即可,需要省显存再换 |
| 上传目录 | 照片落地位置 | 指向规划好的大盘 |
| 外部地址 | 生成分享链接的域名 | 与反向代理域名一致 |
最后一项很容易被漏掉:如果之后要用外链分享照片,服务必须知道自己对外叫什么名字,否则生成的链接是内网地址,别人打开是无效页面。这个值在部署阶段可以先填内网 IP,配好反向代理后再回来改一次,重启服务生效。
资源限额:建议给数据库一个下限
photo 库变大之后,postgres 偶尔会被机器学习或者缩略图进程挤到没内存,表现是页面突然变得很慢、日志里出现连接超时。给 postgres 单独设一个内存下限(reservation)可以根治这类问题,代价是整体常驻占用略升。机器学习服务则相反,它最重要的是不被打断,扫描期间 CPU 占用高是正常的,不要给它限额限到跑不完。
启动后的首次配置
容器起来之后,打开浏览器访问服务端口,第一次进入会让你注册管理员账号。这里回到上一章的提醒:管理员只管设置不管照片,注册完直接去建家人账号,别把管理员当自己的相册用。
接着是几个一次性开关:确认存储模板按日期分目录、检查时区分组是否正确、把默认上传目录指到规划好的位置。如果照片已经有几万张,首次扫描可以在睡前触发,第二天起来看结果。

卷映射是部署的核心
卷映射回答的是数据放在哪这个问题。Compose 里每个服务都配有一组映射,左边是主机路径、右边是容器内路径。把主机路径理解成柜子,容器路径是软件以为的抽屉——软件往抽屉里放东西,东西实际落在你的柜子里。容器删了重建,柜子里的东西还在,这正是卷映射存在的意义。
需要映射的主要有三处:上传目录(照片落盘的位置)、数据库目录(postgres 的数据卷)、机器学习缓存目录(模型文件)。前两处不可省,第三处可以默认。路径选择上回到上一章的三件事:照片目录指向大盘,数据库目录单独放,这样备份和扩容都方便。
权限是新手卡得最多的一步。容器进程通常以普通用户身份运行,如果主机目录的属主不对,服务启动就会报拒绝访问。一把梭的做法是先确认目录存在、再按官方示例里的用户 ID 对齐权限,报错日志里一般会直接写明期望的用户编号。
| 卷 | 作用 | 位置建议 |
|---|---|---|
| 上传目录 | 照片落盘 | 大盘,单独目录 |
| 数据库 | 元数据 | 固态盘,单独卷 |
| 模型缓存 | 机器学习模型 | 默认即可 |
常见启动故障速查
部署卡住的位置几乎集中在几类,对应解法也都很固定。第一类是数据库连不上:要么密码和 Compose 里写的不一致,要么 postgres 还没就绪 server 就已经开始连接。第二类是卷权限拒绝:主机目录的属主和容器用户对不上,日志里会有明确的编号。第三类是机器学习服务拉模型超时:网络问题居多,重试或者配置代理之后通常解决。
| 报错关键词 | 大概率原因 | 解法 |
|---|---|---|
| 拒绝连接 | 服务未就绪或端口错 | 等待、检查端口映射 |
| 权限拒绝 | 目录属主不对 | 对齐容器用户权限 |
| 拉取超时 | 网络问题 | 重试或配置代理 |
| 密码错误 | 环境变量不一致 | 统一密码后重建 |
| 依赖循环 | depends_on 配置错 | 按官方示例还原 |
| 磁盘满 | 卷映射到了小盘 | 迁移卷到大盘 |
一个心理建设:第一次部署报错两三轮非常正常,每解决一类报错就离成功近一步。按官方文档走到这一步的读者,剩下的问题都是一次搜索能解决的层级。如果连续卡在同一个报错上超过半小时,贴出完整报错日志去问,比盯着它发呆有效。报错信息往往直接指向具体文件名和行号,耐着性子读两行,胜过盲目重启十次。
小结
Compose 文件的读法是逐服务拆开:server 是核心,postgres 是数据命脉,machine-learning 掌管智能功能,redis 和 web 各管体验。真正需要决策的只有版本、卷映射、几个环境变量,其余照抄官方示例即可。下一章我们专门聊聊机器学习模型怎么选、显存怎么配。
延伸阅读
- 上一章《部署前要定的三件事》:卷映射的规划来源。
- 《自建 NAS 完全指南》:卷映射与权限的系统讲法。
- 《群晖 DSM 实用指南》:群晖上用容器部署时的目录权限差异。
