外观
更新与备份容器
完成后,你的容器有一份定时的备份,更新是你有意识地做的一件事而不是碰运气,数据库类应用有一条对数据库安全的备份路径,并且你知道更新出问题时怎么退回去。
先看全局:备份分三层
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 的界面定义里它默认不勾选,以你界面上显示的为准。
默认的备份流程
- 停止正在运行的容器(
docker compose stop),原本就停着的不动。 - 用 rsync 把 compose 文件和选中的卷复制到 备份 共享文件夹,位置是
<备份共享文件夹>/<名称>/,compose 文件放在编号0的子目录里,每个卷占一个编号目录。每次都会覆盖上一份。 - 重新启动备份前在运行的容器。
- 复制
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 等),不要勾选这一项,保持默认的停机备份,或者改用应用自带的导出。
- 怎么回退:取消勾选。已经做过的热备份,当作不可靠的,先做一次停机备份,并用恢复演练验证。
各应用的做法,细节在各自的文章里:
| 应用 | 数据库 | 安全的做法 |
|---|---|---|
| Immich | PostgreSQL 容器 | 自带每日数据库转储,再备份整个上传目录,先备数据库、后备文件 |
| Paperless-ngx | PostgreSQL 容器 | 自带 document_exporter 导出文档和元数据,再配合停机备份 |
| Nextcloud | MariaDB 或 PostgreSQL | AIO 用自带的 borg 备份,不在插件备份范围内;官方镜像要先开维护模式再导出数据库 |
| Vaultwarden | SQLite | vaultwarden backup 或 sqlite3 .backup,或者停机后复制 |
| Uptime Kuma | SQLite | 停止容器后备份 data 目录,这是官方说的唯一支持的备份方式 |
| Jellyfin | SQLite | 10.11 起有自带备份,或者停机后复制配置目录 |
恢复
服务 → Compose → 恢复(Restore)页列出备份目录里的备份。选一个,点 恢复(Restore):
- 停止受影响的容器。
- 还原 compose 文件和数据,如果有
global.env也一并还原。 - 重新启动此前在运行的容器。
恢复 global.env(Restore global.env)只还原全局环境变量,不停容器。删除(Delete)会永久删掉那份备份,不能撤销。
恢复会覆盖现有的文件和数据
- 影响范围:恢复用 rsync 把备份同步回原位,对目录类的卷还带
--delete,所以备份之后新增的文件会被删掉,目标目录会和备份时一模一样。borg 后端则是先删掉目标目录,再提取归档。 - 前置条件:先确认选的是哪个时间点,并且把现在的状态另存一份,比如用 rsync 把现有数据目录复制到别处。
- 怎么回退:恢复本身没有撤销,只能用你恢复前另存的那一份。
整机重装 OMV 后,装好插件,设置同样的共享文件夹,恢复页就能看到旧备份。按源码,备份里的 compose 文件在 OMV 里不存在时,恢复会把它加回数据库,并先把 config.xml 复制一份到 /root/config_<时间>.xml。
更新容器
手动更新
服务 → Compose → 文件,选中应用,点 拉取(pull)。只想更新一个服务,也可以在服务页选中它拉取。- 点 上线(up)。容器用新镜像重建,数据目录不变。
- 工具栏 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 文件里,上线可以重建,但容器里没挂载出来的数据会丢。
检查结果
- 建一个只针对小应用的备份任务,比如过滤填
uptime-kuma,点 运行。备份共享文件夹里出现<名称>/0/,以及每个卷的编号目录,日志里没有报错。 - 在备份里找一个你知道体积的卷,确认它真的在。如果不在,对照上面的「哪些卷会被备份」。
- 做一次恢复演练:在测试应用里改一个设置,点 恢复,确认设置回到了备份时的样子。方法见恢复演练。
- 保存计划后点过应用,系统里才有对应的定时任务。
常见问题
备份里没有某个卷。 检查它是不是 :ro、行尾有没有 # SKIP_BACKUP、是不是超过了 最大尺寸。
备份期间应用打不开。 这是预期的行为:停止、备份、启动。把执行时间放到夜里。
更新后容器起不来。 先看日志,再看发布说明里有没有需要手动处理的改动。镜像标签回退见上文,数据已经迁移过就只能恢复备份。见容器启动失败。
计划任务没有按时运行。 确认保存后点过应用。系统里的定时文件是 /etc/cron.d/omv-compose-backup、omv-compose-update 等,在 OMV 的 shell 里(root)可以看到。
备份盘满了。 rsync 后端每个应用只占一份,满了说明数据本身变大了。borg 后端调小 Borg 保留。