展开代码# 查看目录总大小(决定打包策略) du -sh /var/lib/docker # 查看子目录分布,识别大文件/日志(可提前清理) du -h --max-depth=1 /var/lib/docker | sort -hr # 估算传输时间(示例:100GB 数据,10Mbps 带宽 ≈ 22 小时) # 公式:GB × 8 × 1024 / Mbps / 3600 = 小时 echo "100 * 8 * 1024 / 10 / 3600" | bc
展开代码# 进入 Docker 目录 cd /var/lib/docker # 清理悬空镜像/容器/卷(可选,谨慎操作) docker system prune -a --volumes -f # 查看清理后大小 du -sh .
展开代码# 中转机:确认磁盘空间 > 2 倍数据量(打包文件 + 解压缓冲) ssh user@中转机 "df -h /tmp" # 中转机:确认网络带宽与稳定性 ssh user@中转机 "curl -s https://speed.hetzner.de/10GB.bin -o /dev/null -w '%{speed_download}'"
展开代码# 停止所有运行中的容器(避免运行时数据不一致) docker stop $(docker ps -q) # 停止 Docker 守护进程(关键!确保无后台写操作) systemctl stop docker systemctl stop docker.socket # 双重确认无残留进程 ps aux | grep -E 'docker|containerd' | grep -v grep # 应无输出,若有则 kill -9
展开代码# LVM 场景:创建快照备份点 lvcreate -L 100G -s -n docker_snap /dev/vg0/docker_lv # Btrfs 场景:创建子卷快照 btrfs subvolume snapshot /var/lib/docker /var/lib/docker_snap_$(date +%F)
展开代码cd /var/lib # 核心命令:保留 SELinux 标签、ACL、扩展属性、硬链接 tar \ --create \ --gzip \ --preserve-permissions \ --acls \ # 保留 ACL 访问控制列表 --xattrs \ # 保留 SELinux/capabilities --selinux \ # 显式保留 SELinux 上下文 --numeric-owner \ # 保留 UID/GID 数字(跨系统兼容) --sparse \ # 稀疏文件优化 --totals \ # 显示打包统计 --file=docker_$(date +%Y%m%d_%H%M%S).tgz \ docker/ # 简写形式 tar --xattrs --acls -czpf docker_$(date +%Y%m%d_%H%M%S).tgz docker/
展开代码# 生成 SHA256 校验和(传输后比对) sha256sum docker_20240204_143022.tgz > docker_20240204_143022.tgz.sha256 # 验证 tar 文件可读(不解压) tar -tzf docker_20240204_143022.tgz | head -20
| 场景 | 工具 | 命令 | 特点 |
|---|---|---|---|
| 小文件/快速 | scp | scp -P 22 docker.tgz user@中转机:/backup/ | 简单,断点续传弱 |
| 大文件/不稳定 | rsync | rsync -avzP --bwlimit=10000 docker.tgz user@中转机:/backup/ | 断点续传,限速 |
| 加密传输 | scp +压缩 | `gzip -c docker.tgz | ssh user@中转机 "gzip -d > /backup/docker.tgz"` |
| 公网/低带宽 | rclone | rclone copy docker.tgz remote:backup/ | 多云存储,分片 |
展开代码# 限速 10MB/s,显示进度,断点续传 rsync \ --archive \ --compress \ --partial \ # 断点续传 --progress \ # 显示进度条 --bwlimit=10000 \ # 限速 KB/s(避免打满带宽) --rsh="ssh -p 22 -o ConnectTimeout=60" \ docker_20240204_143022.tgz \ docker_20240204_143022.tgz.sha256 \ user@中转机:/backup/docker_migration/ # 传输完成后,中转机校验 ssh user@中转机 "cd /backup/docker_migration && sha256sum -c *.sha256"
展开代码# 方式1:SSH 隧道加密(默认) # 方式2:GPG 预加密(极高安全) gpg --symmetric --cipher-algo AES256 --compress-algo 1 --output docker.tgz.gpg docker.tgz rsync docker.tgz.gpg user@中转机:/backup/
展开代码ssh user@中转机 " mkdir -p /backup/docker_migration/{original,verified,logs} cd /backup/docker_migration ls -lah "
展开代码ssh user@中转机 " cd /backup/docker_migration # 校验 SHA256 sha256sum -c docker_20240204_143022.tgz.sha256 # 测试解压(不落地,仅验证) tar -tzf docker_20240204_143022.tgz | wc -l echo '文件数量应 > 10000' "
展开代码# 记录当前 Docker 状态 docker ps -a > /root/docker_ps_backup.txt docker images > /root/docker_images_backup.txt docker volume ls > /root/docker_volumes_backup.txt # 打包 /etc/docker 配置 tar -czpf /root/docker_etc_backup.tgz /etc/docker/
展开代码# 确认已停机 systemctl status docker # 应为 inactive # 重命名目录(非删除,可快速回滚) mv /var/lib/docker /var/lib/docker_old_$(date +%F) # 或彻底删除(确认中转机已备份后) # rm -rf /var/lib/docker
展开代码# 创建空目录(权限预置) mkdir -p /var/lib/docker chmod 0711 /var/lib/docker
展开代码cd /var/lib # 同样用 rsync 断点续传 rsync \ --archive \ --partial \ --progress \ --bwlimit=10000 \ user@中转机:/backup/docker_migration/docker_20240204_143022.tgz \ user@中转机:/backup/docker_migration/docker_20240204_143022.tgz.sha256 \ ./ # 本地校验 sha256sum -c docker_20240204_143022.tgz.sha256
展开代码cd /var/lib # 核心解压命令(与打包参数对应) tar \ --extract \ --gzip \ --preserve-permissions \ --acls \ --xattrs \ --selinux \ --numeric-owner \ --totals \ --file=docker_20240204_143022.tgz # 简写形式 tar --xattrs --acls -xzpf docker_20240204_143022.tgz # 验证目录权限 ls -la docker/ getfacl docker/ # 查看 ACL ls -Z docker/ # 查看 SELinux 上下文(如启用)
展开代码# 确认 Docker 正常后删除 rm -f docker_20240204_143022.tgz docker_20240204_143022.tgz.sha256 # 可选:删除中转机备份(确认迁移成功) ssh user@中转机 "rm -rf /backup/docker_migration/"
展开代码# 启动服务 systemctl start docker systemctl enable docker # 查看状态 systemctl status docker --no-pager
展开代码# 验证镜像 docker images | head -20 docker images | wc -l # 数量应与之前一致 # 验证容器(应为停止状态) docker ps -a | head -20 docker ps -a | wc -l # 验证卷 docker volume ls # 验证网络 docker network ls # 启动测试容器 docker run --rm hello-world
展开代码# 按依赖顺序启动(示例) docker start <数据库容器> sleep 10 docker start <应用容器> docker start <Web容器> # 验证业务 curl -I http://localhost:8080
展开代码# 立即停止 Docker systemctl stop docker # 恢复旧目录 rm -rf /var/lib/docker mv /var/lib/docker_old_2024-02-04 /var/lib/docker # 启动服务 systemctl start docker # 验证 docker ps -a
| 阶段 | 100GB 数据/10Mbps | 优化手段 |
|---|---|---|
| 停机打包 | 30 分钟 | 提前清理,多核压缩 pigz |
| 传输到中转机 | 22 小时 | 限速避免影响业务,夜间执行 |
| 校验存储 | 10 分钟 | 并行校验 |
| 清理重建 | 5 分钟 | 重命名代替删除 |
| 回传恢复 | 22 小时 | 同传输 |
| 解压验证 | 30 分钟 | SSD 加速 |
| 总计 | ~45 小时 | 建议周末/夜间窗口执行 |
展开代码#!/bin/bash # docker_migrate.sh - 原机→中转机→原机 完整迁移 set -euo pipefail SOURCE_DIR="/var/lib/docker" BACKUP_NAME="docker_$(date +%Y%m%d_%H%M%S)" JUMP_HOST="user@中转机" JUMP_PATH="/backup/docker_migration" # 1. 检查 du -sh $SOURCE_DIR # 2. 停机 systemctl stop docker docker.socket sleep 5 # 3. 打包 cd /var/lib tar --xattrs --acls -czpf ${BACKUP_NAME}.tgz docker/ sha256sum ${BACKUP_NAME}.tgz > ${BACKUP_NAME}.tgz.sha256 # 4. 传输 rsync -avzP --bwlimit=10000 ${BACKUP_NAME}.tgz* $JUMP_HOST:$JUMP_PATH/ # 5. 清理(重命名方式) mv $SOURCE_DIR ${SOURCE_DIR}_old_$(date +%F) mkdir -p $SOURCE_DIR # 6. 回传(模拟,实际需换机器或确认后执行) # rsync -avzP $JUMP_HOST:$JUMP_PATH/${BACKUP_NAME}.tgz* /var/lib/ # 7. 解压 # tar --xattrs --acls -xzpf ${BACKUP_NAME}.tgz # 8. 启动 # systemctl start docker echo "迁移完成,请手动执行步骤 6-8"
注意:脚本还未测试
本文作者:zzz
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!