先明确备份对象
Docker 容器通常可以重新创建,真正需要保护的是配置、持久化数据和数据库一致性。只保存镜像或执行 docker commit,不能代替业务数据备份。
- Compose 文件:compose.yaml、环境变量模板、反向代理配置。
- 持久化目录:bind mount 目录与 named volume。
- 数据库:优先使用数据库自身的 dump/备份机制。
- 恢复材料:镜像版本、网络/端口说明、密钥保管位置和恢复步骤。
一、盘点容器和挂载目录
docker compose ps
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
docker inspect 容器名 --format '{{json .Mounts}}'把每个服务对应的配置文件、挂载源路径、目标路径和数据库类型整理成清单。区分容器内临时目录和真正持久化的数据目录。
二、备份 Compose 配置
建议把部署文件单独纳入版本管理,但只保存不含秘密的模板:
mkdir -p ~/server-backups/config
cp compose.yaml ~/server-backups/config/
cp .env.example ~/server-backups/config/ 2>/dev/null || true
chmod 700 ~/server-backups真实 .env 应通过加密备份保存,或在恢复时从安全存储重新注入。记录镜像 tag,避免只写 latest 导致恢复时版本漂移。
三、备份数据库与文件
数据库优先使用原生备份工具
以 PostgreSQL 为例,可在容器运行期间执行逻辑备份:
docker exec -t 数据库容器名 \
pg_dump -U 数据库用户 -d 数据库名 \
| gzip > ~/server-backups/database-$(date +%F).sql.gzMySQL/MariaDB 应使用对应的 mysqldump 或官方备份工具,并根据引擎、事务表和业务写入情况选择一致性参数。上面的 PostgreSQL 示例不能直接套用到其他数据库。
备份文件目录或 named volume
对普通文件目录可使用 tar。对正在写入的数据库数据目录,不要在数据库运行时简单打包其底层文件;应先使用数据库原生备份,或安排维护窗口并按数据库官方流程停库/快照。
tar --numeric-owner -czf ~/server-backups/app-data-$(date +%F).tar.gz \
-C /srv/app-data ./srv/app-data 只是示例路径,必须替换成真实挂载源目录。
四、异地保存与校验
至少保留一份不在当前 VPS 上的副本。可以使用支持加密的对象存储、另一台服务器或离线介质。遵循 3-2-1 思路:多份副本、不同介质、至少一份异地。
gzip -t ~/server-backups/database-YYYY-MM-DD.sql.gz
tar -tzf ~/server-backups/app-data-YYYY-MM-DD.tar.gz >/dev/null
sha256sum ~/server-backups/* > ~/server-backups/SHA256SUMS校验和只能证明文件传输前后是否一致,不能证明备份内容可恢复。
五、在隔离环境做恢复演练
- 准备临时 VPS 或隔离 Docker 网络,避免覆盖生产服务。
- 恢复 Compose 配置并注入秘密信息。
- 按正确顺序启动数据库,再导入 dump。
- 恢复文件目录和权限,检查 UID/GID、软链接与挂载路径。
- 启动应用,检查登录、核心读写、上传文件和后台任务。
- 记录从拿到备份到服务可用的耗时,形成恢复清单。
六、建立备份节奏
可以按数据变化频率制定每日数据库备份、每周完整文件备份、每月恢复演练的初始计划;生产系统应根据 RPO(可接受的数据丢失时间)和 RTO(可接受的恢复时间)调整。备份失败要有通知,旧备份按保留策略清理,清理前先确认新备份完整且异地副本可用。