最稳妥的docker镜像迁移方式是使用docker save和docker load:在旧服务器批量导出镜像为压缩tar包,通过scp等传至新服务器,再用zcat | docker load一步加载,完整保留镜像层、标签及历史记录,无需网络依赖且兼容v20.10+版本。

Docker 镜像在本地节点间快速复制和迁移,核心在于不依赖远程仓库、最小化网络开销、保留完整镜像结构。最直接高效的方式是使用 docker save + docker load 组合,适用于无公网、内网隔离、离线环境或临时迁移场景。
直接导出再导入(适合单次、少量镜像迁移)
这是最常用、最轻量的方案,全程离线,无需配置仓库,命令简单可靠:
-
导出镜像为 tar 文件
在源机器上执行:docker save -o myapp-v2.3.tar myapp:v2.3
支持同时导出多个镜像到同一文件:
docker save -o full-stack.tar nginx:alpine redis:7-alpine myapp:v2.3
-
拷贝 tar 文件到目标机器
可用任意方式传输(SCP、U盘、rsync、共享目录等):scp myapp-v2.3.tar user@192.168.10.50:/tmp/
-
在目标机器加载镜像
docker load -i /tmp/myapp-v2.3.tar
加载后镜像名、标签、ID 完全一致,可立即
docker run使用。
⚠️ 注意:目标机器 Docker 版本建议 ≥ 源机器(尤其跨大版本时),否则可能因存储驱动或 manifest 格式差异导致兼容问题。
批量镜像同步(适合本地镜像仓库镜像“克隆”)
若你有一台机器作为“本地镜像源”,想把它的全部镜像(或指定列表)同步到另一台机器,可结合脚本自动化:
-
先列出需迁移的镜像(排除基础镜像如
alpine、busybox等可重拉取的):docker images --format "{{.Repository}}:{{.Tag}}" | grep -v '<none>' | grep -E '^(myapp|backend|db-adapter)'</none> -
一键导出+传输+加载(示例脚本逻辑):
# 源机执行 docker save $(docker images --format "{{.Repository}}:{{.Tag}}" | grep myapp) -o all-myapp.tar scp all-myapp.tar target-host:/tmp/ # 目标机执行(自动清理旧镜像可选) docker load -i /tmp/all-myapp.tar
利用私有 registry 实现“准实时”镜像分发(适合多节点长期管理)
如果你已有或愿意快速部署一个轻量私有仓库(如 registry:2),它更适合频繁更新、多节点共享、带权限/审计需求的场景:
-
启动私有 registry(监听 5000 端口):
docker run -d -p 5000:5000 --restart=always --name registry registry:2
-
给本地镜像打 registry 标签并推送:
docker tag myapp:v2.3 localhost:5000/myapp:v2.3 docker push localhost:5000/myapp:v2.3
-
在其他节点拉取(需先配置
insecure-registries):# 编辑 /etc/docker/daemon.json,添加: { "insecure-registries": ["localhost:5000"] } systemctl restart docker docker pull localhost:5000/myapp:v2.3
✅ 优势:支持增量推送、镜像去重、版本回溯、配合 CI 自动触发;
❌ 缺点:需维护 registry 服务,首次部署略多一步。
关键避坑提醒
-
docker export≠docker save:前者只导出容器文件系统(无元数据、无层结构),不能还原为可用镜像;迁移必须用save/load。 - 镜像体积大时,
save生成的 tar 是未压缩的——如需减小传输体积,可额外 gzip:docker save myapp:v2.3 | gzip > myapp-v2.3.tar.gz # 目标机解压并加载: gunzip -c myapp-v2.3.tar.gz | docker load
- 若镜像含多层且某层已存在于目标机,
docker load仍会全部写入——它不智能去重,但不影响功能。
不复杂但容易忽略。











