跳转到内容

更新与备份容器 ​

完成后,你的容器有一份定时的备份,更新是你有意识地做的一件事而不是碰运气,数据库类应用有一条对数据库安全的备份路径,并且你知道更新出问题时怎么退回去。

先看全局:备份分三层 ​

Compose 插件的备份只解决其中一层,别指望它备份一切。

层内容谁来备份
compose 文件和小型配置.yml、.env、几 GB 以内的配置卷Compose 插件的计划备份(本文)
大数据媒体、照片、文档文件备份工具,见 rsync 任务、备份策略
数据库PostgreSQL、MariaDB、SQLite应用自带的导出,或停机备份,见下文

记住这一条:RAID、镜像这类冗余防的是坏盘,误删、勒索、配置改坏都救不了,见备份策略:冗余不是备份。

计划页能做什么 ​

打开 服务 → Compose → 计划(Services → Compose → Schedule),点 创建(Create)。表单分几块:

分区字段说明
设置启用(Enabled)默认开。关掉后任务不自动跑,但仍可以手动运行
过滤(Filter)按 compose 文件的名字匹配,支持 * 通配,多个用逗号分隔,留空或写 * 表示全部。旁边的「选择文件」可以直接勾选
排除过滤器(Exclude filter)先按「过滤」选,再从中排除。适合「全部更新,但 Immich 除外」
卷路径排除(Volume path excludes)传给 rsync 或 borg 的 --exclude,排除卷里面的路径,例如 *.log, cache/。它不会把 compose 文件排除出任务
动作类型维护(Maintenance)勾选后才能选下面的备份、更新、Prune
备份(Backup)备份容器数据。勾上维护后默认选中
跳过容器停止 / 启动(Skip container stop/start)备份时不停容器,下文有警告
更新(Update)拉新镜像,重建容器。同时勾了备份,备份总是先跑
Prune执行 docker image prune -f,清理悬空镜像
Container 状态(Container state)定时开始或停止容器,比如夜里停掉不用的应用
构建(Build)构建、拉取、清理编译器缓存,给用 Dockerfile 的应用
脚本备份前脚本、备份后脚本填脚本路径
计划执行时间(Time of execution)默认每周,可选每日、每月等
通过电子邮件发送命令输出、仅出错时发送邮件需要先配置好邮件通知
详细输出(Verbose)默认开,让 rsync 输出更详细

保存后点黄色提示条上的应用,计划才会写进系统的定时任务。选中任务可以点 运行(Run)立即执行,手动运行不会发邮件。

维护的默认值:omv-extras wiki 写的是默认勾选,但插件 8.2.3 的界面定义里它默认不勾选,以你界面上显示的为准。

默认的备份流程 ​

  1. 停止正在运行的容器(docker compose stop),原本就停着的不动。
  2. 用 rsync 把 compose 文件和选中的卷复制到 备份 共享文件夹,位置是 <备份共享文件夹>/<名称>/,compose 文件放在编号 0 的子目录里,每个卷占一个编号目录。每次都会覆盖上一份。
  3. 重新启动备份前在运行的容器。
  4. 复制 global.env。

日志在 /var/log/omv-compose-backup.log,也可以在 诊断 → 系统日志(Diagnostics → System Logs)里找 Compose 相关的日志类型。

「停止 → 备份 → 启动」的好处是备份期间数据不变,拿到的是一致的拷贝。代价是备份这段时间应用不可用,所以放在夜里。

哪些卷会被备份 ​

备份不备份
compose 文件(.yml、.env、覆盖文件)以 :ro 挂载的卷,永远不备份
绑定挂载的目录、命名卷行尾写了 # SKIP_BACKUP 的卷
行尾写了 # BACKUP 的卷,不管多大超过 最大尺寸 的卷(默认 1 GB),除非行尾有 # BACKUP
/dev、/sys 这类系统路径,套接字等特殊文件
yaml
volumes:
  - ${{ sf:"appdata" }}/jellyfin/config:/config # BACKUP
  - ${{ sf:"media" }}:/media:ro                  # 只读,不会被备份
  - ${{ sf:"downloads" }}:/downloads # SKIP_BACKUP

一个容易踩的坑:默认只备份 1 GB 以内的卷。 Immich 的 PostgreSQL 目录通常有 1–3 GB,Jellyfin 的配置目录更大,它们默认会被悄悄跳过,备份看起来成功了,其实没有它们。要么把设置页的 最大尺寸 调大,要么在这些卷的行尾写 # BACKUP。照片、视频这类大数据则交给文件备份工具。

rsync 与 borg 后端 ​

rsync(默认)borg(8.1.3 起)
保留几份一份,每次覆盖最近 N 次,Borg 保留 默认 7
加密无可选,需要口令
注意备份中途出错,上一份也已经被改了口令丢了就无法恢复

rsync 后端只是「最近的一份拷贝」,不是历史版本。要版本、要去重,用 borg 后端,或者再用别的备份工具备份这个备份目录。备份目录不要和 Docker 数据在同一块盘上。

数据库类应用:怎么备份才安全 ​

容器不停机的备份,对数据库不安全

勾选 跳过容器停止 / 启动 后,插件在容器运行中直接复制文件。插件自己的提示也说了:对数据库等运行中的服务,数据可能不一致。

  • 影响范围:PostgreSQL、MariaDB、SQLite 的文件在被写入时被复制,得到的拷贝可能是损坏的。备份任务不会报错,你要到恢复的那一天才发现。
  • 前置条件:凡是带数据库的应用(Immich、Paperless-ngx、Nextcloud、Vaultwarden、Uptime Kuma、Jellyfin 等),不要勾选这一项,保持默认的停机备份,或者改用应用自带的导出。
  • 怎么回退:取消勾选。已经做过的热备份,当作不可靠的,先做一次停机备份,并用恢复演练验证。

各应用的做法,细节在各自的文章里:

应用数据库安全的做法
ImmichPostgreSQL 容器自带每日数据库转储,再备份整个上传目录,先备数据库、后备文件
Paperless-ngxPostgreSQL 容器自带 document_exporter 导出文档和元数据,再配合停机备份
NextcloudMariaDB 或 PostgreSQLAIO 用自带的 borg 备份,不在插件备份范围内;官方镜像要先开维护模式再导出数据库
VaultwardenSQLitevaultwarden backup 或 sqlite3 .backup,或者停机后复制
Uptime KumaSQLite停止容器后备份 data 目录,这是官方说的唯一支持的备份方式
JellyfinSQLite10.11 起有自带备份,或者停机后复制配置目录

恢复 ​

服务 → Compose → 恢复(Restore)页列出备份目录里的备份。选一个,点 恢复(Restore):

  1. 停止受影响的容器。
  2. 还原 compose 文件和数据,如果有 global.env 也一并还原。
  3. 重新启动此前在运行的容器。

恢复 global.env(Restore global.env)只还原全局环境变量,不停容器。删除(Delete)会永久删掉那份备份,不能撤销。

恢复会覆盖现有的文件和数据

  • 影响范围:恢复用 rsync 把备份同步回原位,对目录类的卷还带 --delete,所以备份之后新增的文件会被删掉,目标目录会和备份时一模一样。borg 后端则是先删掉目标目录,再提取归档。
  • 前置条件:先确认选的是哪个时间点,并且把现在的状态另存一份,比如用 rsync 把现有数据目录复制到别处。
  • 怎么回退:恢复本身没有撤销,只能用你恢复前另存的那一份。

整机重装 OMV 后,装好插件,设置同样的共享文件夹,恢复页就能看到旧备份。按源码,备份里的 compose 文件在 OMV 里不存在时,恢复会把它加回数据库,并先把 config.xml 复制一份到 /root/config_<时间>.xml。

更新容器 ​

手动更新 ​

  1. 服务 → Compose → 文件,选中应用,点 拉取(pull)。只想更新一个服务,也可以在 服务 页选中它拉取。
  2. 点 上线(up)。容器用新镜像重建,数据目录不变。
  3. 工具栏 Prune 菜单里的 镜像,清理失去标签的旧镜像。

计划更新 ​

勾选 维护 里的 更新。更新脚本会先等待正在进行的备份(最多约 30 分钟),拉取镜像,然后只对当时正在运行的应用执行 up -d 重建,停着的应用只拉取、不启动。

更新之前 ​

  • 先备份。 备份和更新同时勾选时,备份总是先跑。
  • 看发布说明。 大版本升级可能要迁移数据库,而且常常不能降级:Jellyfin 官方说它没有降级机制,Immich 也不支持降级;Nextcloud 一次只能升一个大版本;Paperless-ngx v3 只能从 2.20.15 升上去;Uptime Kuma 从 1 到 2 要先备份并等待迁移。
  • 用大版本标签,不要无脑 latest。 latest 会跨大版本。官方提供大版本标签的应用,用它。
  • 别让会做迁移的应用无人值守自动更新。 用 排除过滤器 把它们排除在计划更新之外,手动更新。
  • 想知道哪些镜像有新版,可以装 omv-extras 的 openmediavault-imagecheck,它只检查,不拉取、不重建,见小工具合集。

更新出问题怎么退回去 ​

把镜像标签改回旧版本再上线,只有新版本没有改动数据格式时才安全。新版本已经迁移过数据库的话,旧版本往往读不了,只能用更新前的备份恢复,所以更新前一定要备份。

清理(Prune) ​

工具栏 Prune 按钮,官方中文译作「删除」,执行的命令都带 --force,不会再确认。按 Docker 官方文档,它们清理的是:

菜单项清理什么
系统(System)已停止的容器、没被使用的网络、悬空镜像、没用的构建缓存
Container所有已停止的容器
镜像悬空镜像,也就是更新后失去标签的旧镜像
网络没被使用的网络
卷没被任何容器使用的匿名卷,命名卷不动

注意「已停止的容器」包括你用 停止 停下的应用。它们的配置还在 compose 文件里,上线可以重建,但容器里没挂载出来的数据会丢。

检查结果 ​

  1. 建一个只针对小应用的备份任务,比如过滤填 uptime-kuma,点 运行。备份共享文件夹里出现 <名称>/0/,以及每个卷的编号目录,日志里没有报错。
  2. 在备份里找一个你知道体积的卷,确认它真的在。如果不在,对照上面的「哪些卷会被备份」。
  3. 做一次恢复演练:在测试应用里改一个设置,点 恢复,确认设置回到了备份时的样子。方法见恢复演练。
  4. 保存计划后点过应用,系统里才有对应的定时任务。

常见问题 ​

备份里没有某个卷。 检查它是不是 :ro、行尾有没有 # SKIP_BACKUP、是不是超过了 最大尺寸。

备份期间应用打不开。 这是预期的行为:停止、备份、启动。把执行时间放到夜里。

更新后容器起不来。 先看日志,再看发布说明里有没有需要手动处理的改动。镜像标签回退见上文,数据已经迁移过就只能恢复备份。见容器启动失败。

计划任务没有按时运行。 确认保存后点过应用。系统里的定时文件是 /etc/cron.d/omv-compose-backup、omv-compose-update 等,在 OMV 的 shell 里(root)可以看到。

备份盘满了。 rsync 后端每个应用只占一份,满了说明数据本身变大了。borg 后端调小 Borg 保留。

参考资料 ​

OpenMediaVault 非官方中文使用指南,与 openmediavault 项目及其开发者无隶属关系。