Docker镜像跨机器迁移工程指南

一、迁移方案概览

1.1 方案对比

方案 适用场景 优点 缺点
docker save/load 离线迁移、批量迁移 完整保存镜像层级,保留所有历史 文件较大,不支持增量
docker export/import 容器状态迁移 导出容器当前状态,文件较小 丢失镜像历史信息
Registry仓库 团队协作、持续部署 集中管理,支持版本控制 需要搭建仓库服务
docker commit+迁移 保存容器修改 保存运行时修改 可能包含不必要数据

二、docker save/load 方案(推荐)

2.1 源机器操作:导出镜像

# 1. 查看本地镜像
docker images

# 2. 导出单个镜像(推荐)
docker save -o [输出文件名].tar [镜像名]:[标签]
# 示例:
docker save -o nginx-latest.tar nginx:latest
docker save -o myapp-v1.0.tar myapp:v1.0

# 3. 导出多个镜像到单个文件
docker save -o all-images.tar nginx:latest redis:alpine mysql:5.7

# 4. 使用镜像ID导出(避免重名问题)
docker save -o image-by-id.tar fce289e99eb9

# 5. 导出并压缩(节省空间)
docker save nginx:latest | gzip > nginx-latest.tar.gz

2.2 压缩优化策略

# 方案1:gzip压缩(通用)
docker save myapp:latest | gzip > myapp-latest.tar.gz

# 方案2:pigz压缩(多核加速)
sudo apt install pigz  # Ubuntu/Debian
docker save myapp:latest | pigz > myapp-latest.tar.gz

# 方案3:分卷压缩(大文件传输)
docker save large-image:latest | gzip | split -b 2G - large-image.tar.gz.part

# 方案4:评估镜像大小后再决策
docker image inspect myapp:latest --format='{{.Size}}' | \
  awk '{printf "%.2f GB\n", $1/1024/1024/1024}'

2.3 传输到目标机器

# 方法1:scp(安全复制)
scp nginx-latest.tar user@目标机器IP:/目标路径/
scp -C nginx-latest.tar.gz user@192.168.1.100:/tmp/

# 方法2:rsync(断点续传、增量)
rsync -avP --progress nginx-latest.tar user@目标机器IP:/目标路径/
rsync -avPz --progress nginx-latest.tar.gz user@192.168.1.100:/tmp/

# 方法3:nc(netcat,内网快速传输)
# 接收端先监听:
nc -l 1234 > nginx-latest.tar
# 发送端:
nc 目标机器IP 1234 < nginx-latest.tar

# 方法4:HTTP服务器(多机分发)
python3 -m http.server 8000  # 在源机器启动
# 目标机器下载:
curl -O http://源机器IP:8000/nginx-latest.tar

2.4 目标机器操作:导入镜像

# 1. 基本导入
docker load -i nginx-latest.tar

# 2. 从压缩文件导入
docker load < nginx-latest.tar.gz
gzip -dc nginx-latest.tar.gz | docker load

# 3. 查看导入的镜像
docker images

# 4. 批量导入多个镜像
tar -xf all-images.tar -O | docker load

# 5. 导入后重新打标签(如果需要)
docker tag 镜像ID 新镜像名:新标签

三、Registry仓库方案(生产环境推荐)

3.1 私有仓库搭建与使用

# 1. 启动私有Registry容器
docker run -d \
  -p 5000:5000 \
  --name registry \
  -v /data/registry:/var/lib/registry \
  --restart=always \
  registry:2

# 2. 标记镜像指向私有仓库
docker tag nginx:latest localhost:5000/nginx:latest
docker tag myapp:v1.0 192.168.1.100:5000/myapp:v1.0

# 3. 推送到私有仓库
docker push localhost:5000/nginx:latest
docker push 192.168.1.100:5000/myapp:v1.0

# 4. 从目标机器拉取
docker pull 192.168.1.100:5000/nginx:latest

# 5. 查看仓库中的镜像
curl http://localhost:5000/v2/_catalog
curl http://localhost:5000/v2/nginx/tags/list

3.2 安全认证配置

# 1. 创建认证文件
mkdir -p auth
docker run --rm \
  --entrypoint htpasswd \
  httpd:2 -Bbn username password > auth/htpasswd

# 2. 启动带认证的Registry
docker run -d \
  -p 5000:5000 \
  --name registry \
  -v /data/registry:/var/lib/registry \
  -v $(pwd)/auth:/auth \
  -e "REGISTRY_AUTH=htpasswd" \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
  registry:2

# 3. 登录认证
docker login 192.168.1.100:5000

四、高级批量操作脚本

4.1 批量导出脚本 export-images.sh

#!/bin/bash
# 批量导出所有镜像

BACKUP_DIR="./docker-backup-$(date +%Y%m%d_%H%M%S)"
mkdir -p $BACKUP_DIR

echo "开始导出Docker镜像..."

# 导出所有镜像
docker images --format "{{.Repository}}:{{.Tag}}" | while read image
do
    if [[ "$image" != "<none>:<none>" ]]; then
        echo "正在导出: $image"
        filename=$(echo $image | sed 's/[\/:]/-/g')
        docker save $image | gzip > "$BACKUP_DIR/${filename}.tar.gz"
    fi
done

echo "导出完成!文件保存在: $BACKUP_DIR"
echo "总大小: $(du -sh $BACKUP_DIR | cut -f1)"

4.2 批量导入脚本 import-images.sh

#!/bin/bash
# 批量导入镜像

IMPORT_DIR="$1"

if [[ -z "$IMPORT_DIR" || ! -d "$IMPORT_DIR" ]]; then
    echo "用法: $0 [镜像目录]"
    exit 1
fi

echo "开始导入Docker镜像..."

for file in $IMPORT_DIR/*.tar.gz; do
    if [[ -f "$file" ]]; then
        echo "正在导入: $(basename $file)"
        gunzip -c "$file" | docker load
    fi
done

echo "导入完成!"
docker images

4.3 镜像同步工具 sync-images.sh

#!/bin/bash
# 同步镜像到远程机器

REMOTE_USER="user"
REMOTE_HOST="192.168.1.100"
REMOTE_PATH="/tmp/docker-images"
IMAGE_LIST=("nginx:latest" "redis:alpine")

# 1. 在远程创建目录
ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $REMOTE_PATH"

# 2. 导出并传输每个镜像
for image in "${IMAGE_LIST[@]}"; do
    echo "处理镜像: $image"

    # 导出镜像
    filename=$(echo $image | sed 's/[\/:]/-/g').tar
    docker save -o $filename $image

    # 传输到远程
    scp $filename $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/

    # 在远程导入
    ssh $REMOTE_USER@$REMOTE_HOST "docker load -i $REMOTE_PATH/$filename"

    # 清理本地文件
    rm $filename
done

echo "镜像同步完成!"

五、验证与最佳实践

5.1 完整性验证

# 1. 导出后验证
sha256sum nginx-latest.tar > nginx-latest.tar.sha256

# 2. 传输后验证
scp nginx-latest.tar.sha256 user@目标机器IP:/tmp/
ssh user@目标机器IP "cd /tmp && sha256sum -c nginx-latest.tar.sha256"

# 3. 导入后验证
docker images --digests | grep nginx
docker inspect nginx:latest --format='{{.Id}}'

5.2 空间清理

# 1. 清理传输文件
rm -f *.tar *.tar.gz

# 2. 清理无用镜像
docker image prune -f

# 3. 清理悬空镜像
docker image prune -a -f

# 4. 清理构建缓存
docker builder prune -f

5.3 性能优化建议

  1. 网络优化 ```bash # 使用压缩传输 scp -C source.tar user@host:/path/

# 调整docker守护进程并行下载数 echo '{"max-concurrent-downloads": 3}' > /etc/docker/daemon.json ```

  1. 磁盘优化 ```bash # 导出前清理不必要的层 docker export | docker import

# 使用小基础镜像 FROM alpine:latest # 而非 ubuntu:latest ```

  1. 批量操作优化 bash # 并行导出 parallel -j 4 docker save {} \| gzip \> {}.tar.gz ::: $(docker images -q)

六、故障排查

常见问题及解决方案

  1. 空间不足 ```bash # 检查磁盘空间 df -h

# 清理docker缓存 docker system df docker system prune -af ```

  1. 导入失败 ```bash # 检查文件完整性 tar -tf image.tar | head

# 检查docker版本兼容性 docker version

# 尝试重新导出 docker save --format docker-archive -o new-image.tar image:tag ```

  1. 权限问题 ```bash # 使用sudo sudo docker load -i image.tar

# 或将用户加入docker组 sudo usermod -aG docker $USER ```

七、自动化流程示例

# docker-compose迁移示例
version: '3.8'
services:
  # 源服务定义
  app:
    image: myapp:${TAG:-latest}
    build: .

  # 导出任务
  exporter:
    image: alpine
    command: >
      sh -c "
      apk add --no-cache docker &&
      docker save myapp:latest | gzip > /backup/myapp.tar.gz"
    volumes:
      - ./backup:/backup
      - /var/run/docker.sock:/var/run/docker.sock

总结建议

场景选择指南:

  1. 开发环境迁移:使用 docker save/load + 压缩
  2. 生产环境部署:使用私有Registry + 版本标签
  3. 持续集成/持续部署:Registry + 自动化脚本
  4. 大规模集群:Registry镜像仓库 + 分布式存储

关键检查点:

  • [ ] 镜像完整性验证(SHA256校验)
  • [ ] 磁盘空间充足(源端和目标端)
  • [ ] 网络带宽评估(大镜像分时段传输)
  • [ ] 版本兼容性(Docker版本匹配)
  • [ ] 安全策略(镜像来源可信)

通过本指南,您可以系统化地进行Docker镜像的跨机器迁移操作,确保迁移过程的可靠性、高效性和可追溯性。