
Docker 镜像导入导出:离线环境下的镜像迁移指南
2026/6/22大约 9 分钟

离线环境、网络隔离、跨服务器迁移...
当你无法直接 pull 镜像时,
Docker 镜像的导入导出就是你的救星。
为什么需要镜像导入导出?
常见的场景:
┌─────────────────────────────────────────────────────────┐
│ 需要镜像导入导出的场景 │
├─────────────────────────────────────────────────────────┤
│ │
│ 场景 1:离线环境 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ · 生产环境与互联网隔离 │ │
│ │ · 无法直接访问 Docker Hub │ │
│ │ · 需要在有网环境下载,再迁移到离线环境 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 场景 2:跨服务器迁移 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ · 从开发服务器迁移到生产服务器 │ │
│ │ · 从旧服务器迁移到新服务器 │ │
│ │ · 服务器之间网络受限或不稳定 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 场景 3:镜像备份 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ · 重要镜像的本地备份 │ │
│ │ · 防止镜像仓库故障 │ │
│ │ · 版本快照和回滚 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 场景 4:CI/CD 流程 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ · 构建服务器导出镜像 │ │
│ │ · 部署服务器导入镜像 │ │
│ │ · 自动化部署流程 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘核心命令一览
Docker 镜像导入导出涉及四个核心命令:
┌─────────────────────────────────────────────────────────┐
│ 四个核心命令 │
├─────────────────────────────────────────────────────────┤
│ │
│ 命令 1:docker save │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 作用:将镜像保存为 tar 文件 │ │
│ │ 用途:导出单个或多个镜像 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 命令 2:docker load │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 作用:从 tar 文件加载镜像 │ │
│ │ 用途:导入导出的镜像 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 命令 3:docker export │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 作用:将容器导出为 tar 文件 │ │
│ │ 用途:导出容器的文件系统 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 命令 4:docker import │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 作用:从 tar 文件导入为镜像 │ │
│ │ 用途:导入导出的容器文件系统 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘关键区别:
docker save&docker load:镜像级别的操作,保留所有层和元数据docker export&docker import:容器级别的操作,只保存当前文件系统
方案一:docker save & docker load
这是最常用的方案,适用于镜像迁移。
docker save:导出镜像
基本用法:
# 导出单个镜像
docker save -o nginx.tar nginx:latest
# 或使用输出重定向
docker save nginx:latest > nginx.tar
# 导出多个镜像
docker save -o images.tar nginx:latest redis:alpine mysql:8.0
# 导出镜像到指定目录
docker save -o /backup/nginx.tar nginx:latest参数说明:
-o:指定输出文件名- 也可以使用
>输出重定向
生成的文件特点:
- 包含镜像的所有层
- 包含镜像的元数据(标签、环境变量等)
- 文件通常较大(包含所有历史层)
docker load:导入镜像
基本用法:
# 从 tar 文件导入镜像
docker load -i nginx.tar
# 或使用输入重定向
docker load < nginx.tar
# 从指定目录导入
docker load -i /backup/nginx.tar参数说明:
-i:指定输入文件名- 也可以使用
<输入重定向
导入后的结果:
- 镜像的所有层都被恢复
- 镜像的标签和元数据都被保留
- 可以直接使用导入的镜像启动容器
完整示例
场景:从开发服务器迁移到生产服务器
# 在开发服务器(有网络)上:
# 1. 拉取所需镜像
docker pull nginx:latest
docker pull redis:alpine
docker pull mysql:8.0
# 2. 导出镜像
docker save -o nginx.tar nginx:latest
docker save -o redis.tar redis:alpine
docker save -o mysql.tar mysql:8.0
# 或一次性导出多个镜像
docker save -o app-images.tar nginx:latest redis:alpine mysql:8.0
# 3. 将 tar 文件传输到生产服务器
# (使用 scp、U盘、或其他方式)
scp app-images.tar user@production-server:/tmp/
# 在生产服务器(无网络)上:
# 4. 导入镜像
docker load -i /tmp/app-images.tar
# 5. 验证导入
docker images
# 6. 启动容器
docker run -d -p 80:80 --name web nginx:latest方案二:docker export & docker import
这个方案适用于容器快照,不推荐用于常规镜像迁移。
docker export:导出容器
基本用法:
# 导出正在运行的容器
docker export nginx-container > nginx-container.tar
# 导出已停止的容器
docker export nginx-container -o nginx-container.tar
# 导出容器到指定目录
docker export nginx-container -o /backup/nginx-container.tar与 docker save 的区别:
docker export导出的是容器的文件系统- 不包含镜像的历史层
- 只包含容器当前状态的所有文件
- 文件通常比
docker save小(只保留当前状态)
docker import:导入为镜像
基本用法:
# 从 tar 文件导入为镜像
docker import nginx-container.tar nginx:snapshot
# 导入时指定新的标签
docker import nginx-container.tar my-nginx:v1.0
# 导入时指定变更(应用 Dockerfile 指令)
docker import nginx-container.tar my-nginx:v2.0 \"
--change "ENV DEBUG=true" \
--change "CMD [\"nginx\", \"-g\", \"daemon off;\"]"参数说明:
- 最后一个参数是为新镜像指定的标签
--change:可以在导入时应用 Dockerfile 指令
与 docker load 的区别:
docker import创建的是一个全新的镜像- 不保留原始镜像的层结构
- 会丢失原始镜像的元数据和历史
完整示例
场景:容器状态快照和恢复
# 在服务器 A 上:
# 1. 运行容器
docker run -d --name my-app nginx:latest
# 2. 在容器中做一些修改
docker exec my-app apt-get update
docker exec my-app apt-get install -y curl
# 3. 导出容器(包含所有修改)
docker export my-app > my-app-snapshot.tar
# 4. 传输到服务器 B
scp my-app-snapshot.tar user@server-b:/tmp/
# 在服务器 B 上:
# 5. 导入为镜像
docker import /tmp/my-app-snapshot.tar my-app:customized
# 6. 启动新容器(包含所有修改)
docker run -d --name new-app my-app:customized两种方案的选择
┌─────────────────────────────────────────────────────────┐
│ 两种方案的选择决策 │
├─────────────────────────────────────────────────────────┤
│ │
│ 使用 docker save & load │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 适用于: │ │
│ │ · 镜像迁移(开发 → 生产) │ │
│ │ · 离线环境部署 │ │
│ │ · 镜像备份 │ │
│ │ · 需要保留所有层和元数据 │ │
│ │ │ │
│ │ 优点: │ │
│ │ · 保留完整的镜像结构 │ │
│ │ · 保留所有历史层 │ │
│ │ · 保留镜像标签和元数据 │ │
│ │ │ │
│ │ 缺点: │ │
│ │ · 文件较大(包含所有历史层) │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 使用 docker export & import │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 适用于: │ │
│ │ · 容器快照 │ │
│ │ · 容器状态备份 │ │
│ │ · 需要保存容器的当前修改 │ │
│ │ │ │
│ │ 优点: │ │
│ │ · 文件较小(只包含当前状态) │ │
│ │ · 包含容器的运行时修改 │ │
│ │ │ │
│ │ 缺点: │ │
│ │ · 丢失镜像的历史层 │ │
│ │ · 丢失原始镜像的元数据 │ │
│ │ · 不适合常规镜像迁移 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘选择建议:
- 99% 的情况使用
docker save&docker load - 只有在需要保存容器运行时修改时才使用
docker export&docker import
压缩优化
镜像文件通常很大,可以通过压缩减少传输时间。
使用 gzip 压缩
# 导出时直接压缩
docker save nginx:latest | gzip > nginx.tar.gz
# 导出时使用更高压缩级别
docker save nginx:latest | gzip -9 > nginx.tar.gz
# 导入时解压
gunzip -c nginx.tar.gz | docker load压缩效果:
- 通常可以减少 50-70% 的文件大小
- 压缩时间增加,但传输时间大幅减少
- 适合网络传输
使用 pigz(并行压缩)
# 使用 pigz 进行并行压缩(更快)
docker save nginx:latest | pigz > nginx.tar.gz
# 使用 pigz 解压
pigz -d nginx.tar.gz | docker loadpigz 优势:
- 多线程并行压缩
- 在多核 CPU 上速度显著快于 gzip
- 压缩格式与 gzip 兼容
实战场景:离线环境部署
场景:在线环境准备镜像,离线环境部署应用
在线环境(有网络)
#!/bin/bash
# prepare-images.sh
# 定义需要迁移的镜像列表
images=(
"nginx:latest"
"redis:alpine"
"mysql:8.0"
"postgres:15"
)
# 拉取所有镜像
for image in "${images[@]}"; do
echo "Pulling $image..."
docker pull "$image"
done
# 导出所有镜像到一个文件
echo "Exporting images..."
docker save -o app-images.tar "${images[@]}"
# 压缩
echo "Compressing..."
gzip -f app-images.tar
echo "Done! Transfer app-images.tar.gz to offline environment."离线环境(无网络)
#!/bin/bash
# deploy-images.sh
# 解压并导入镜像
echo "Loading images..."
gunzip -c app-images.tar.gz | docker load
# 验证导入
echo "Verifying imported images..."
docker images
# 启动应用
echo "Starting application..."
docker-compose up -d
echo "Done!"进阶技巧
技巧 1:只导出需要的层
如果镜像有很多层,但只需要最后几层:
# 方案:使用 docker export 导出容器
docker run --name temp-container nginx:latest
docker export temp-container > nginx-minimal.tar
docker import nginx-minimal.tar nginx:minimal
docker rm temp-container缺点: 丢失所有历史层,不推荐用于生产环境。
技巧 2:批量导出所有镜像
备份所有本地镜像:
#!/bin/bash
# backup-all-images.sh
# 获取所有镜像 ID
image_ids=$(docker images -q)
# 导出所有镜像
echo "Exporting all images..."
docker save -o all-images.tar $image_ids
# 压缩
echo "Compressing..."
gzip -f all-images.tar
echo "Done! Saved as all-images.tar.gz"技巧 3:按标签分组导出
将不同应用的镜像分组导出:
#!/bin/bash
# export-by-tag.sh
# 导出所有 web 相关镜像
docker save -o web-images.tar \
$(docker images --filter=label=app=web -q)
# 导出所有 database 相关镜像
docker save -o db-images.tar \
$(docker images --filter=label=app=database -q)
echo "Done! Images exported by tag."技巧 4:验证镜像完整性
在传输后验证镜像是否损坏:
#!/bin/bash
# verify-image.sh
image_file="$1"
# 计算 SHA256 校验和
echo "Calculating checksum..."
sha256sum "$image_file" > "$image_file.sha256"
# 在导入前验证
echo "Verifying..."
sha256sum -c "$image_file.sha256"
if [ $? -eq 0 ]; then
echo "Checksum OK. Loading image..."
docker load -i "$image_file"
else
echo "Checksum FAILED! File may be corrupted."
exit 1
fi常见问题
问题 1:导入后镜像没有标签
现象:
docker images
# 显示镜像,但 TAG 列为 <none>原因: 导出时使用了镜像 ID 而不是标签。
解决:
# 导出时使用标签
docker save -o nginx.tar nginx:latest
# 或导入后重新打标签
docker tag <image-id> nginx:latest问题 2:导入时提示 "Error loading image"
可能原因:
- 文件传输过程中损坏
- 文件格式不正确
- 使用了错误的导入命令(如用 import 导入 save 的输出)
解决:
# 1. 验证文件完整性
sha256sum nginx.tar
# 2. 确保使用正确的命令
# 如果是 docker save 导出的,必须用 docker load 导入
docker load -i nginx.tar
# 如果是 docker export 导出的,必须用 docker import 导入
docker import nginx.tar nginx:tag问题 3:文件太大,传输太慢
解决:
# 1. 使用压缩
docker save nginx:latest | gzip > nginx.tar.gz
# 2. 使用并行压缩(更快)
docker save nginx:latest | pigz > nginx.tar.gz
# 3. 分批导出,分别传输
docker save -o nginx.tar nginx:latest
docker save -o redis.tar redis:alpine
docker save -o mysql.tar mysql:8.0最佳实践
1. 版本控制
为导出的镜像文件添加版本信息:
# 使用镜像标签和日期命名
docker save -o nginx-1.21-2023-12-01.tar nginx:1.21
# 或使用 Git 风格的版本号
docker save -o myapp-v1.0.0.tar myapp:1.0.02. 文档化
为每个导出的镜像创建说明文档:
# nginx-images-README.md
cat > nginx-images-README.md << 'EOF'
# Nginx 镜像包
## 镜像列表
- nginx:1.21.6
- nginx:1.22
- nginx:latest
## 导出时间
2023-12-01 10:30:00
## 导出命令
docker save -o nginx-images.tar nginx:1.21.6 nginx:1.22 nginx:latest
## 导入命令
docker load -i nginx-images.tar
## 校验和
SHA256: abc123...
EOF3. 自动化脚本
创建可重用的镜像迁移脚本:
#!/bin/bash
# image-migration.sh
set -e
MODE="$1"
IMAGE="$2"
FILE="$3"
case "$MODE" in
export)
echo "Exporting $IMAGE to $FILE..."
docker save -o "$FILE" "$IMAGE"
gzip -f "$FILE"
echo "Exported to $FILE.gz"
;;
import)
echo "Importing from $FILE..."
gunzip -c "$FILE" | docker load
echo "Import completed"
;;
*)
echo "Usage: $0 {export|import} <image> <file>"
exit 1
;;
esac4. 安全考虑
敏感数据处理:
# 导出前清理敏感数据
docker exec <container> sh -c "rm -f /tmp/secrets/*"
# 或使用 Dockerfile 的 .dockerignore
# 排除敏感文件
echo "secrets/" >> .dockerignore收尾金句
- 离线环境、网络隔离、跨服务器迁移,当你无法直接 pull 镜像时,Docker 镜像的导入导出就是你的救星
- docker save & load:镜像级别的操作,保留所有层和元数据
- docker export & import:容器级别的操作,只保存当前文件系统
- 99% 的情况使用 docker save & load
- 压缩可以减少 50-70% 的文件大小
- 为导出的镜像文件添加版本信息和文档
- 自动化脚本可以简化镜像迁移流程
Docker 镜像导入导出
离线环境下的镜像迁移指南
