Immich 数据库迁移到统一 PostgreSQL 容器(完整流程 + 脚本)

本文记录了将 Immich 从原本独立的 immich-postgres 数据库迁移到新的统一 PostgreSQL 数据库容器的完整步骤。迁移目标是让多个项目共享同一个公用数据库容器,以简

分享

本文记录了将 Immich 从原本独立的 immich-postgres 数据库迁移到新的统一 PostgreSQL 数据库容器的完整步骤。迁移目标是让多个项目共享同一个公用数据库容器,以简化维护、提高性能并统一备份策略。

以下流程适用于基于 Docker + Portainer 环境的部署。


📌 目录

  1. 创建新的 PostgreSQL 公用容器
  2. 从旧的 immich-postgres 中导出数据
  3. 在新库中创建用户与数据库(空库)
  4. 为新数据库安装扩展、配置权限
  5. 恢复数据到新库(必须使用超级用户)
  6. 验证恢复结果
  7. 修改 Immich 服务配置,使其使用新的数据库(基于 URL 连接方式)
  8. 迁移检查与收尾

1. 创建新的 PostgreSQL 公用容器(global-postgres)

1.1 创建共享网络(global-net)

docker network create global-net

或在 Portainer:
Networks → Add network → Name: global-net → Create

1.2 在 Portainer 中创建新的 PostgreSQL Stack

这里使用 Immich 官方镜像的 PostgreSQL 扩展版(包含 pgvector、vchord、cube 等)。

docker-compose.yml:

version: "3.9"

services:
  postgres:
    container_name: global-postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: super_strong_password
    volumes:
      - /opt/global-postgres/data:/var/lib/postgresql/data
    networks:
      - global-net

networks:
  global-net:
    external: true

在 Portainer 中:

Stacks → Add Stack → 粘贴上方 compose → Deploy

2. 从旧的 immich-postgres 中导出数据库备份

假设旧容器名为:immich_postgres
以下命令在宿主机执行。

docker exec immich_postgres \
  pg_dump -U postgres immich > /root/immich_backup.sql

根据你的实际用户/数据库名调整 postgres 和 immich。

3. 在新 PostgreSQL 中创建用户与数据库(空库)

3.1 创建需要的用户

docker exec -it global-postgres \
  psql -U postgres -c "CREATE USER immich_user WITH PASSWORD 'immich_password';"

3.2 创建空库(暂由 postgres 拥有)

docker exec -it global-postgres \
  psql -U postgres -c "CREATE DATABASE immich;"

4. 在空库中安装 Immich 所需扩展

进入新数据库:

docker exec -it global-postgres psql -U postgres -d immich

安装扩展(按 Immich 官方要求):

CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;
CREATE EXTENSION vector;
CREATE EXTENSION vchord;
\q

5. 恢复备份文件到新数据库(必须使用 postgres)

5.1 将备份复制到容器

docker cp /root/immich_backup.sql global-postgres:/tmp/immich_backup.sql

5.2 用超级用户恢复(不可用 immich_user)

docker exec -it global-postgres \
  psql -U postgres -d immich -f /tmp/immich_backup.sql

⚠️ 注意:
如果恢复过程中大量 ERROR 提示“某类型不存在”,说明扩展未成功安装,需要返回「步骤 4」重新执行。

6. 数据恢复后验证内容是否正确导入

6.1 查看所有扩展

docker exec -it global-postgres \
  psql -U postgres -d immich -c "\dx"

应至少看到:

vector
vchord
cube
earthdistance

6.2 查看表数量

docker exec -it global-postgres \
  psql -U postgres -d immich -c "\dt"

应看到大量表,例如:

assets
albums
users
face_search
smart_search
...

6.3 检查表数量是否合理

docker exec -it global-postgres \
  psql -U postgres -d immich -c "SELECT COUNT(*) FROM pg_tables WHERE schemaname='public';"

7. 修改 Immich 服务器,使其使用新的 PostgreSQL

⚠️ Immich 官方文档要求使用 DB_URL,而非 DB_HOST。

示例配置:

7.1 修改 immich-server 的环境变量

将:

DB_HOST=immich_postgres
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=password
DB_DATABASE_NAME=immich

改为:

DB_URL=postgresql://immich_user:immich_password@global-postgres:5432/immich

7.2 让 Immich 容器加入 global-net

在 docker-compose 或 Portainer stack 中添加:

networks:
  - global-net

确保:

networks:
  global-net:
    external: true

7.3 最终示例(immich-server 部分)

services:
  immich-server:
    ...
    environment:
      DB_URL: postgresql://immich_user:immich_password@global-postgres:5432/immich
    networks:
      - default
      - global-net

然后在 Portainer 中:

Update Stack → Immich 自动重建

8. 启动 Immich 并验证

进入 Immich Web:

  • 能看到全部照片
  • 用户账户存在
  • 地图功能正常(earthdistance)
  • 人脸识别功能正常(vector + vchord)
  • 搜索功能可正常使用

说明迁移成功。

确认无误后,可删除旧容器:

docker stop immich_postgres
docker rm immich_postgres

📦 完整流程来源说明(可用于 Blog 注脚)

迁移流程参考了以下来源与最佳实践:

  • Immich 官方文档数据库配置章节
  • PostgreSQL 官方扩展安装文档
  • Docker 官方文档关于容器数据迁移方法
  • pg_dump/psql 官方备份恢复流程
  • 社区在 Immich + pgvector 场景下的迁移案例

🎉 结语

通过以上流程,你已经成功实现:

✔ 把 Immich 数据库迁移到统一 PostgreSQL 服务
✔ 实现多个项目共享数据库容器
✔ 清晰控制用户权限
✔ 正确处理扩展,包括 vector、vchord、cube、earthdistance
✔ 使用官方推荐的 URL 连接方式配置 Immich
✔ 未来可以轻松扩展到 Plausible、Paperless 等项目

相关代码:

CREATE USER immich_user WITH PASSWORD 'immich_password';
CREATE DATABASE immich OWNER immich_user;
GRANT ALL PRIVILEGES ON DATABASE immich TO immich_user;
\c immich

GRANT ALL ON SCHEMA public TO immich_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON TABLES TO immich_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT ALL ON SEQUENCES TO immich_user;


SELECT datname, datdba::regrole FROM pg_database WHERE datname='immich';


CREATE EXTENSION IF NOT EXISTS cube;
CREATE EXTENSION IF NOT EXISTS earthdistance;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS vchord;
\q
docker exec immich_postgres \
  pg_dump -U postgres immich > immich_backup.sql

docker cp immich_backup.sql global-postgres:/tmp/immich_backup.sql

docker exec -it global-postgres \
  psql -U immich_user -d immich -f /tmp/immich_backup.sql


docker exec -it global-postgres \
  psql -U postgres -d immich -f /tmp/immich_backup.sql

Tranmoo Journal

按标签浏览