“我要把 A 服务器上跑得好好的容器,搬到 B 服务器上去”——这种需求在生产环境很常见,但很多人会卡在 save / export 该用哪个。这一篇把镜像 / 容器的导入导出分清楚,再给出几个常见场景的实战方案。
阅读对象:需要在不同环境之间迁移容器 / 镜像、要做离线备份的运维 / 开发者 覆盖范围:save vs export + load vs import + 容器打包成新镜像 + 批量备份脚本
一、四种命令的差异
| 命令 | 对象 | 保留历史 | 保留元数据 | 典型用途 |
|---|---|---|---|---|
docker save | 镜像 | 是(所有层) | 是 | 镜像备份、离线迁移 |
docker load | 镜像 | 加载 save 产物 | 是 | 镜像恢复 |
docker export | 容器 | 否(扁平化) | 否 | 容器快照 |
docker import | 容器 export 产物 | 加载成新镜像 | 否 | 从容器快照恢复 |
核心区别:
save/load操作的是镜像,保留完整历史(每一层构建步骤、tag、标签)export/import操作的是容器当前文件系统快照,扁平化成单层,丢失历史export出来的 import 后默认无 tag,需要手动docker tag
二、save / load:镜像备份与离线迁移
| |
保留:
- 镜像名、tag
- 所有构建历史(
docker history能看到每一层)- 标签 / env / 入口点等元数据
| |
注意:
save默认输出到 stdout(用>重定向),load默认从 stdin 读取(用<喂入)。
三、export / import:容器快照
| |
| |
丢弃:
- 所有构建历史——扁平化为单层
- 容器名 / 标签 / 启动参数——只是个文件系统快照
- 环境变量 / 入口点——可以 import 后用
docker run重新指定
典型场景:容器 A 上有手动修改的文件(不写在 Dockerfile 里),想"原样"搬走。
export拿到的就是 A 当前文件系统。
四、把运行中的容器打包成新镜像
需求:服务器 A 上一个容器跑得好好的,有大量数据 + 手工修改,直接迁移到 B 上。
| |
Why 用
commit而不是export:commit把容器当前的差异化层(基于原镜像的修改)保留下来,新镜像的"基础层"还是原镜像——体积小、有历史、FROM关系清晰。export是纯文件系统,体积大且无继承。
五、批量备份所有镜像
| |
六、常见问题
6.1 docker load 之后镜像名变长 hash
save 没指定镜像名时,load 后镜像名是 hash:
| |
解决:手动 tag。
| |
6.2 跨大版本 Docker 不兼容
docker save 产物在跨大版本 Docker 之间可能不能 load:
- Docker 1.10+ 改了镜像 schema,老 daemon 可能不认新镜像
- 新 daemon 一般能 load 老镜像(向后兼容)
如果跨大版本不兼容:
| |
如果还不行,升级老 daemon 或用 docker pull + 私有 registry 中转。
6.3 save 文件很大,传输慢
镜像层是去重的,多个镜像可以合并成一个 save 文件:
| |
load 后所有镜像都会出现。
七、save / export 的取舍速查
| 场景 | 推荐 |
|---|---|
| 离线环境装镜像 | save / load |
| 容器整体迁移到另一台机器 | commit + save + load |
| 容器当前状态备份(含手工修改) | export / import |
| 镜像要保留构建历史 | save / load |
| 大镜像分发 | 私有 registry + docker push / pull(更高效) |
| 跨大版本 Docker | 升级老 daemon 或走 registry 中转 |
八、生产最佳实践
- 优先用私有 registry——
docker push/pull内部仓库比save/load更快、支持增量、可以做权限控制 save文件作为离线备份、应急恢复用——不要作为日常分发方式- 写 Dockerfile + rebuild——比 commit 容器更可追溯、更可复现
- CI 流水线用 commit / tag 标识版本,避免"无 tag 镜像"堆积
九、要点回顾
save/load保留历史,export/import扁平化- commit + save + load 是"运行中容器迁移"的标准三件套
- 跨大版本 Docker
save/load可能不兼容——优先升级 daemon - 多镜像可以合并到一个
save文件(-oflag) load后无 tag 要手动docker tag命名
十、小结
把镜像 / 容器的导入导出搞清楚,离线环境、内部 Harbor / Registry 没起来的应急场景都能 hold 住。但生产环境强烈建议走私有 registry——save / load 是"应急"工具,不是"日常"工具。
下一步:理解了单镜像的导入导出,下一步是 Harbor / Docker Registry / Distribution 私有仓库的搭建、镜像签名、漏洞扫描——
save/load解决"单文件"问题,registry 解决"仓库级"问题。
