核心是利用rsync对宿主机挂载路径增量同步:绑定挂载直接同步宿主机路径,命名卷需通过docker inspect查宿主机对应路径;推荐宿主机cron+rsync定时执行,避免操作容器可写层。

核心在于把 rsync 的增量同步能力,和 Docker 的挂载机制结合起来——不是在容器里“备份容器”,而是对挂载到容器里的真实数据路径做同步。
明确要同步的数据位置
rsync 操作对象必须是宿主机上的实际路径,而不是容器内部路径。先确认你的应用数据落盘在哪:
- 如果是绑定挂载(-v /host/path:/app/data),直接同步 /host/path
- 如果是命名卷(-v mydb:/var/lib/mysql),运行 docker inspect 容器名 | grep -A 10 "Mounts" 找到宿主机对应路径,通常是 /var/lib/docker/volumes/mydb/_data
- 别碰容器可写层(/overlay2/...)——那里没持久数据,删容器就没了
用宿主机 cron + rsync 定时拉取
最稳妥的方式:在宿主机上定时执行 rsync,把挂载目录同步到备份位置。这样不依赖容器运行状态,也不用进容器装工具。
- 示例命令:rsync -aAXH --delete /host/data/ /backup/data_$(date +\%Y\%m\%d)/
- 加 --delete 保证备份与源一致;-aAXH 保留权限、ACL、链接等关键属性
- 配合 crontab 每日凌晨执行,再写个脚本自动清理 7 天前的快照目录
容器内运行 rsync(仅限必要场景)
如果必须由容器触发(比如同步 binlog 到远端),需确保三点:
- 容器启动时通过 -v 把宿主机数据目录和备份脚本都挂载进来(如 -v /host/mysql:/data -v /host/scripts:/scripts)
- Dockerfile 中安装 rsync 和 ssh 客户端(apk add --no-cache rsync openssh 或 apt-get install -y rsync openssh-client)
- 脚本里用 rsync 拉取或推送时,操作路径必须是挂载进来的宿主机路径(/data),不是容器内虚构路径
避免常见坑
同步失败往往不是 rsync 问题,而是挂载或权限导致:
- 绑定挂载目录属主不匹配(比如 MySQL 要求 mysql:mysql,但宿主机目录是 root:root)——同步后恢复会出错
- SELinux 启用时(CentOS/RHEL),宿主机目录需打上正确上下文:chcon -Rt svirt_sandbox_file_t /host/data
- 命名卷路径默认权限受限,docker volume inspect 查看挂载点后,确认宿主机用户有读取权限


















