首页
/ Immich 备份与恢复完全指南:数据库转储、资产文件系统与回滚机制

Immich 备份与恢复完全指南:数据库转储、资产文件系统与回滚机制

2026-09-06 21:06:05作者:贡沫苏Truman

本文基于 Immich 官方文档 备份与恢复 编写,覆盖数据库自动备份的原理与配置、Web 界面与命令行两种恢复路径、文件系统中各类资产的存储位置,以及备份顺序等容易出错的关键细节。读完本文,你将能够为 Immich 实例制定一套完整的数据库加文件备份方案,并掌握从设置页、首次安装引导页或纯命令行三种方式恢复数据库的实操步骤。

从管理后台恢复数据库备份界面

全新安装时从备份恢复的引导界面

核心原则:为什么必须同时备份数据库和文件

官方推荐采用 3-2-1 备份策略(3 份数据副本、2 种不同介质、1 份异地)来保护照片数据。一个完整的 Immich 备份必须同时包含两部分:

  • 已上传的照片/视频原始文件;
  • Immich 数据库。

这一点至关重要,因为 Immich 把文件路径和用户元数据都存放在数据库里,它不会去扫描图库文件夹来重建索引。换句话说,只备份照片文件而没有数据库备份,恢复后文件将“无人认领”;反之只备份数据库而没有文件,则所有资产都会显示为缺失。

注意:官方文档中的步骤只说明如何为 Immich 实例“做好被备份的准备”、应该备份哪些文件;真正执行备份动作、选择什么备份工具,仍需要你自己完成。

数据库备份

自动数据库备份

Immich 内置了面向灾难恢复的数据库自动备份功能:

  • 备份文件存储在 UPLOAD_LOCATION/backups 目录中,并可通过管理后台(Web 界面)管理;
  • Administration > Settings > Backup 中可以调整备份计划与保留策略,默认值为:保留最近 14 份备份,每天凌晨 2:00 创建一份(默认值可在源码 server/src/dtos/config.dto.ts 中确认:enabled: truecronExpression: CronExpression.EVERY_DAY_AT_2AMkeepLastAmount: 14)。

注意:数据库备份只包含元数据,不包含任何照片或视频。它必须与 UPLOAD_LOCATION 中文件的一份拷贝配合使用才有意义。

从源码 server/src/services/database-backup.service.ts 的实现可以看到几个细节:

  • 备份通过 pg_dump 导出后用 gzip --rsyncable 压缩,先写入 .tmp 临时文件、成功后再重命名为正式文件名(server/src/services/database-backup.service.ts)。文件名格式为 immich-db-backup-<时间戳>-v<Immich版本>-pg<Postgres版本>.sql.gz,这正是管理后台能识别备份版本号的依据;
  • 每次备份完成后会执行清理逻辑:删除超过 keepLastAmount 的旧备份,并清理所有以 .tmp 结尾的失败备份文件(cleanupDatabaseBackups);
  • 服务启动时会通过数据库锁(DatabaseLock.BackupDatabase)决定由哪个节点承担备份任务,避免多副本部署时重复备份。

手动创建一次备份

如果不想等待定时任务,可以手动触发一次数据库转储:

  1. 进入 Administration > Job Queues
  2. 点击右上角 Create job
  3. 选择 Create Database Dump 并点击 Confirm

生成的备份会出现在 UPLOAD_LOCATION/backups 中,并且同样计入保留数量上限。

从设置页恢复数据库备份

已有 Immich 实例时,推荐使用 Web 界面恢复:

  1. 进入 Administration > Maintenance
  2. 展开 Restore database backup 区域;
  3. 列表中会展示所有可用备份及其版本号与创建时间;
  4. 在目标备份旁点击 Restore
  5. 确认恢复操作。

恢复备份会清空当前数据库并用备份内容替换。操作开始前系统会自动创建一个恢复点(restore point),以便恢复失败时回滚。

从首次安装引导页恢复(全新实例)

如果是在全新安装上恢复已有备份,步骤如下:

  1. 按照 安装指南 下载并配置好 .envdocker-compose.yml
  2. 将旧实例数据目录中 backupsencoded-videolibraryprofilethumbsupload 六个文件夹移动到新的 UPLOAD_LOCATION 下;
  3. (使用过外部图库的用户) 如果之前的实例使用了 external library 功能,确保新 docker-compose.yml 中的挂载设置与旧结构一致,必要时移动相应文件。

文件迁移示例:假设旧实例为 UPLOAD_LOCATION=/my-broken-instance/media,新实例为 UPLOAD_LOCATION=/a-brand-new-instance/data,需要执行如下移动:

/my-broken-instance/media/backups          ->    /a-brand-new-instance/data/backups
/my-broken-instance/media/encoded-video    ->    /a-brand-new-instance/data/encoded-video
/my-broken-instance/media/library          ->    /a-brand-new-instance/data/library
/my-broken-instance/media/profile          ->    /a-brand-new-instance/data/profile
/my-broken-instance/media/thumbs           ->    /a-brand-new-instance/data/thumbs
/my-broken-instance/media/upload           ->    /a-brand-new-instance/data/upload
  1. docker compose up -d 启动 Immich 服务;
  2. 在欢迎页点击 Restore from backup
  3. Immich 会进入维护模式,并对存储文件夹执行完整性检查;
  4. 查看文件夹状态,确认图库文件可读;
  5. 点击 Next 进入备份选择;
  6. 从列表中选择一份备份,或直接上传备份文件(.sql.gz);
  7. 点击 Restore 开始恢复。

提示:恢复前请确认 UPLOAD_LOCATION 中的文件夹包含备份创建时存在的那些文件。完整性检查会显示每个文件夹是否可读/可写以及文件数量。

直接上传备份文件

不经过实例自动备份时,也可以直接上传备份文件:

  1. Restore database backup 区域点击 Select from computer
  2. 选择一个 .sql.gz 文件;
  3. 上传后的备份会以 uploaded- 前缀出现在列表中(源码中 uploadBackup 方法会给上传文件加该前缀,见 server/src/services/database-backup.service.ts);
  4. 点击 Restore 从上传的文件恢复。

备份版本兼容性

查看备份列表时,Immich 会根据当前版本与文件名中解析出的版本显示兼容性标识:

  • 绿色对勾:备份版本与当前 Immich 版本一致;
  • 黄色感叹号:备份由其他版本的 Immich 创建;
  • 红色感叹号:无法从文件名确定备份版本。

警告:跨版本恢复可能需要执行数据库迁移。恢复流程会尝试自动运行迁移,但条件允许时仍应尽量选择与备份版本兼容的目标版本。

恢复流程内部机制

文档描述的恢复流程在源码 restoreDatabaseBackup 中有完整实现,实际执行顺序为:

  1. 先为当前数据库创建一个恢复点备份(文件名带 restore-point- 前缀);
  2. 恢复前会先终止其他数据库连接并重建 public schema,然后解压备份(支持 .gz 与纯 .sql)通过 psql 单事务导入;
  3. 如需要则运行数据库迁移(runMigrations);
  4. 执行健康检查:确认存在管理员用户(hasAdmin)并调用 checkApiHealth 验证 API 正常。

如果任何一步失败(例如备份损坏、缺少管理员用户),Immich 会自动将数据库回滚到恢复点,保证数据库不会停留在半新半旧的损坏状态。另外,源码中的版本校验逻辑要求 Postgres 主版本落在 >=14 <19 区间,不满足时会抛出 UnsupportedPostgresError 使恢复中止(server/src/services/database-backup.service.ts)。

命令行备份与恢复

面向高级用户或自动化恢复场景,可以用命令行完成。以下命令中 <DB_USERNAME> 替换为数据库用户名(默认为 postgres),<DB_DATABASE_NAME> 替换为数据库名(默认为 immich)。

Linux 系统

备份:

# <DB_USERNAME> 通常为 postgres,<DB_DATABASE_NAME> 通常为 immich
docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME> | gzip > "/path/to/backup/dump.sql.gz"

恢复:

docker compose down -v  # 警告!删除所有 Immich 数据,从零开始
## 如需彻底重置 Postgres,取消下一行注释并把 DB_DATA_LOCATION 替换为你的 Postgres 数据路径
# rm -rf DB_DATA_LOCATION # 警告!删除所有 Immich 数据,从零开始
docker compose pull             # (可选)更新到 Immich 最新版本
docker compose create           # 创建但不启动 Immich 应用容器
docker start immich_postgres    # 启动 Postgres
sleep 10                        # 等待 Postgres 就绪
# 如果你修改过默认值,请核对数据库用户
# <DB_USERNAME> 通常为 postgres,<DB_DATABASE_NAME> 通常为 immich
gunzip --stdout "/path/to/backup/dump.sql.gz" \
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
| docker exec -i immich_postgres psql --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME> --single-transaction --set ON_ERROR_STOP=on  # 恢复备份
docker compose up -d            # 启动 Immich 其余应用

Windows 系统(PowerShell)

备份:

# <DB_USERNAME> 通常为 postgres,<DB_DATABASE_NAME> 通常为 immich
[System.IO.File]::WriteAllLines("C:\absolute\path\to\backup\dump.sql", (docker exec -t immich_postgres pg_dump --clean --if-exists --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME>))

恢复:

docker compose down -v  # 警告!删除所有 Immich 数据,从零开始
## 如需彻底重置 Postgres,取消下一行注释并把 DB_DATA_LOCATION 替换为你的 Postgres 数据路径
# Remove-Item -Recurse -Force DB_DATA_LOCATION # 警告!删除所有 Immich 数据,从零开始
## 建议在 docker-compose.yml 中把备份挂载为 volume,例如:- 'C:\path\to\backup\dump.sql:/dump.sql'
docker compose pull                               # (可选)更新到 Immich 最新版本
docker compose create                             # 创建但不启动 Immich 应用容器
docker start immich_postgres                      # 启动 Postgres
sleep 10                                          # 等待 Postgres 就绪
docker exec -it immich_postgres bash              # 进入容器 Shell 执行以下命令
# 如果备份是 .gz 结尾,把 cat 换成 gunzip --stdout
# <DB_USERNAME> 通常为 postgres,<DB_DATABASE_NAME> 通常为 immich
cat "/dump.sql" | sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" | psql --dbname=<DB_DATABASE_NAME> --username=<DB_USERNAME> --single-transaction --set ON_ERROR_STOP=on
exit                                              # 退出容器 Shell
docker compose up -d                              # 启动 Immich 其余应用

命令行恢复的注意事项

  • 版本说明:备份与恢复流程在 v2.5.0 有所变更,如果你的备份由旧版 Immich 创建,请在文档版本选择器中查找对应版本的恢复方法。
  • 要求全新安装:命令行恢复需要数据库处于“从未运行过”的干净状态(Docker 容器创建后 Immich server 从未启动)。如果应用已经运行过,可能出现 Postgres 冲突(relation already exists、外键约束冲突等),此时需要删除 DB_DATA_LOCATION 文件夹重置数据库。
  • DB_SKIP_MIGRATIONS=true:某些部署方式下无法在不启动 server 的情况下单独启动数据库。此时可在启动服务前设置环境变量 DB_SKIP_MIGRATIONS=true,阻止 server 运行会干扰恢复流程的迁移;数据库恢复完成后移除该变量并重启服务即可(该变量定义于 server/src/dtos/env.dto.ts)。
  • 单事务提交:恢复命令中的 --single-transaction --set ON_ERROR_STOP=on 保证所有变更在一个事务中提交,数据库绝不会停留在损坏状态;如果某些场景不希望这样,可以移除这两个参数。

文件系统备份

Immich 不会替你处理文件系统备份,这部分必须自行安排。文件系统中有两类内容:

  • (a)原始、未修改的资产(照片和视频);
  • (b)生成内容(缩略图、转码视频等)。

官方建议直接备份 UPLOAD_LOCATION 的全部内容,但其中真正关键的只有原始内容,位于以下三个文件夹:

  1. UPLOAD_LOCATION/library
  2. UPLOAD_LOCATION/upload
  3. UPLOAD_LOCATION/profile

如果只备份这三个文件夹,恢复后需要重新运行所有资产的转码和缩略图生成任务来重建生成内容。

注意:如果你把其中某些文件夹(如 profile/)挪到了其他存储设备上,请相应调整备份路径。

资产类型与存储位置

部分存储位置受存储模板(Storage Template)开关影响。以 v1.92.0 起的新机器为例,默认不会使用 UPLOAD_LOCATION/library,只有管理员激活存储模板引擎后资产才会进入 library/

用户专属目录:每个用户有一个唯一的 user ID(账号设置页 Account 中可见)。

资产类型 说明 存储位置
源资产(Storage Template 关闭,默认) 通过浏览器、移动端、CLI 上传的原始资产 UPLOAD_LOCATION/upload/<userID>
头像图片 用户资料图片 UPLOAD_LOCATION/profile/<userID>
缩略图 每个资产的小图/大图预览及识别人脸缩略图 UPLOAD_LOCATION/thumbs/<userID>
转码资产 为兼容播放而转码的视频(原始文件不删除) UPLOAD_LOCATION/encoded-video/<userID>
数据库转储备份 Immich 自动创建的灾难恢复备份 UPLOAD_LOCATION/backups/
Postgres 数据 系统运行所需的全部数据库内容 DB_DATA_LOCATION(仅当采用了把 Postgres 数据目录移入管理范围内的可选变更,或从该版本起步的新安装时才会出现)

开启 Storage Template 时的差异:

  • 激活存储模板引擎后,资产会被移动到 UPLOAD_LOCATION/library/<userID>
  • 关闭引擎后资产不会迁回 upload/,留在 library/<userID>,只有新资产才写入 UPLOAD_LOCATION/upload
  • 管理员可以为用户设置 Storage Label,library/ 目录下用它代替 <userID>;Admin 的默认 storage label 为 admin
  • 移动端上传的文件先暂存于 UPLOAD_LOCATION/upload/<userID>,上传成功后再转入 UPLOAD_LOCATION/library/<userID>

警告:除备份之外,任何情况下都不要直接改动或删除上述文件夹内的文件。变更或删除资产会导致文件变为未跟踪或丢失状态。把文件系统当作“只能透过 App 操作”的黑盒:查看、修改、删除资产只能通过移动端或浏览器界面进行。

备份顺序:先数据库,后文件

一套完整的 Immich 备份应同时包含数据库和资产文件。两者在备份窗口内可能失去同步,恢复后表现为“损坏的资产”。处理方式:

  • 最佳做法:在备份期间停止 immich-server 容器。没有变更发生时,备份必然一致;
  • 无法停服时:推荐顺序是先备份数据库,再备份文件系统。最坏情况只是文件系统中存在数据库“不知道”的文件——这些文件可以在恢复后手动(重新)上传;
  • 反过来的顺序(先文件后数据库)是危险的:恢复后的数据库可能引用文件系统备份中不存在的文件,从而产生损坏的资产。

附:Borg 定时备份脚本模板

Immich 官方另提供了一份可每日/每周以 cron 任务运行的 Borg 备份脚本模板:先用 pg_dump 把数据库导出到 UPLOAD_LOCATION/database-backup 子目录,再用 Borg 对 UPLOAD_LOCATION 做增量、去重的快照备份,并按 --keep-weekly=4 --keep-monthly=3 策略清理旧快照;恢复时用 borg mount 挂载快照取回文件。该脚本与内置自动备份的关系值得注意:由于脚本在每次库备份的同时执行数据库备份、且快照与资产严格同步,使用它之后可以安全地在管理后台关闭内置的自动数据库备份以节省存储空间。

小结

Immich 的备份体系可以概括为三层:内置的 pg_dump 自动转储(管理后台可触发、可配置保留份数与计划)、UPLOAD_LOCATION 文件系统中三类关键目录(library/upload/profile)、以及正确的备份顺序(先库后文件)。恢复路径上,Web 界面(含恢复点自动创建与失败回滚)覆盖了绝大多数场景,命令行方式则保留给自动化与深度定制需求。只要坚持“数据库 + 原始文件必须成对备份”这一核心原则,实例的数据安全性就有扎实保障。

登录后查看全文
热门项目推荐
相关项目推荐