本文以 Docker + docker-compose 部署的 Immich 为例,记录一次 从群晖 NFS 迁移 PostgreSQL 数据库到本地磁盘 的完整过程,适用于 ESXi / PVE / 物理机环境。
一、背景与问题
原始架构
- ESXi
- Ubuntu Server(虚拟机)
- Docker + docker-compose
- 群晖 NAS 通过 NFS 提供存储
- Immich 运行在 Ubuntu 上
初始问题
- PostgreSQL 数据目录位于 NFS
- 群晖不常开机
- 群晖关机 → NFS 不可达
- Immich / Emby 卡死
- 只能通过 重启虚拟机 恢复
核心原则
数据库必须放在本地磁盘 NFS 只适合:
- 成品文件(照片 / 视频)
- 可丢失缓存(ML cache)
二、目标架构
| 内容 | 存储位置 |
|---|---|
| PostgreSQL(pgdata) | Ubuntu 本地 |
| Immich cache / geodata / i18n | Ubuntu 本地 |
| 照片(upload) | 群晖 NFS |
| ML cache | 群晖 NFS(可丢失) |
三、准备工作
停止 Immich
cd /root/docker/immich
docker compose down
创建本地目录
mkdir -p /root/docker/immich/{pgdata,geodata,cache}
复制 geodata(非数据库,可直接拷贝)
rsync -avh /mnt/immich/geodata/ /root/docker/immich/geodata/
四、导出旧数据库(NFS → SQL)
注意
PostgreSQL 禁止直接复制 pgdata 目录,NFS 上物理复制极易损坏数据。
必须使用 逻辑备份(pg_dump)。
启动旧数据库(仍然指向 NFS)
docker compose up -d database
使用示例凭据导出数据库
示例参数(请自行替换):
数据库用户:DB_USER
数据库名称:DB_NAME
数据库密码:DB_PASSWORD
导出命令:
docker exec -e PGPASSWORD='DB_PASSWORD' -t immich_db \
pg_dump -U DB_USER -d DB_NAME \
> /root/docker/immich/immich.sql \
2> /root/docker/immich/pg_dump.err
校验:
ls -lh immich.sql pg_dump.err
正常情况:
immich.sql:几十 MB ~ 数百 MBpg_dump.err:空
五、切换数据库到本地磁盘
修改 docker-compose.yml
将 database 的 volume 从:
- /mnt/immich/pgdata:/var/lib/postgresql/data
改为:
- ./pgdata:/var/lib/postgresql/data
启动新的本地数据库(空库)
docker compose up -d database
查看日志:
docker logs --tail=50 immich_db
出现 initdb / CREATE DATABASE 表示新库初始化成功。
六、导入数据库到本地
cat /root/docker/immich/immich.sql | \
docker exec -e PGPASSWORD='DB_PASSWORD' -i immich_db \
psql -U DB_USER -d DB_NAME
导入完成后检查数据体积:
du -sh /root/docker/immich/pgdata
七、验证导入是否成功
Immich 用户表验证
Immich 使用的是 public."user"(注意是保留关键字):
docker exec -e PGPASSWORD='DB_PASSWORD' -it immich_db \
psql -U DB_USER -d DB_NAME \
-c 'select count(*) from public."user";'
如果返回 ≥ 1,说明数据已成功导入。
八、启动 Immich 全套服务
cd /root/docker/immich
docker compose up -d
九、最终校验(非常重要)
数据库是否已完全本地化
docker inspect immich_db --format '{{range .Mounts}}{{println .Source "->" .Destination}}{{end}}'
期望结果:
/root/docker/immich/pgdata -> /var/lib/postgresql/data
十、NFS 挂载建议(示例)
NAS_IP:/photos /mnt/photos nfs rw,soft,noatime,_netdev,x-systemd.automount,timeo=600,retrans=5 0 0
关键点
禁止 hard
使用 soft
使用 x-systemd.automount- 群晖关机 ≠ 系统卡死
十一、最终效果
- 群晖关机:
- Immich 数据库正常
- Ubuntu 不再卡死
- Immich 稳定性显著提升
- NFS 仅作为“文件存储层”
十二、一句话总结
数据库永远不要跑在 NFS 上。 NFS 适合文件,不适合有状态服务。