Docker(四)_导出容器(不含历史层)
常用的导出并起容器步骤为
1、docker commit
2、docker save -o
3、docker load -i
4、docker run
1.镜像空间变大
发现每次调试后容器占用空间都会变大,如下图:

原始的34.5、多次调试后44.1,增长了约10G,其实并没有
使用以下命令清理了下缓存后,由44.1减小到41.8
# 清 apt 缓存
rm -rf /var/lib/apt/lists/*
rm -rf /var/cache/apt/*# 清 pip 缓存
rm -rf ~/.cache/pip# 清日志
find /var/log -type f -name "*.log" -delete# 清 tmp
rm -rf /tmp/*
2.排查空间增大原因
感觉还是不对劲,因为我并没有增加什么文件,于是用以下命令排查所有目录
du -h --max-depth=1 / | sort -hr | head -n 20
du -h --max-depth=1 /
du:Disk Usage,磁盘使用情况命令,用于查看文件或目录占用的磁盘空间大小。h:human-readable,人类可读的格式,用KB、MB、GB等单位显示大小,方便理解。-max-depth=1:只显示指定目录/下的一级子目录及文件的大小总和,而不递归显示更深层的子目录。/:目标路径,这里是根目录。
总结: 这部分的作用是列出根目录 / 下一级子目录和文件各自占用的空间大小,以易读的格式显示。
|
管道符,把前面命令 du -h ... 的输出结果传递给后面命令作为输入。
sort -hr
sort:排序命令。h:human numeric sort,按人类可读的数字排序,能够识别K,M,G等单位正确排序(否则只按字母顺序排序,结果会不对)。r:reverse,倒序排序,也就是从大到小排序。
总结: 对 du 输出的目录大小进行从大到小排序。
head -n 20
head:显示文本的前几行。n 20:显示前20行。
总结: 只输出排序后的前20条数据,也就是占用空间最大的20个目录或文件。
输出结果
2.9T /
2.8T /data
19G /usr
990M /opt
570M /workspace
530M /root
332M /dev
16M /var
2.4M /etc
96K /run
16K /.singularity.d
12K /proc
8.0K /tmp
4.0K /srv
4.0K /mnt
4.0K /media
4.0K /home
4.0K /boot
0 /sys
为什么 /data 是挂载目录(外部 volume),但容器 commit 后镜像仍有 42G(commit不会把挂载目录打包)?
计算下,除了/data目录,其余文件加起来约21G,多出来的21G哪里来的?
3.原因解释
Docker 层叠文件系统导致 “已删除但未释放”空间仍在镜像里
容器内删除某些大文件(如 .tar.gz, .whl, .pt)后,如果没 docker export 或 docker squash,它们的空间仍保留在镜像层中。如:
pip install torch # 下载几GB安装包 rm -rf ~/.cache/pip # 看似删除了但实际上,在 AUFS/overlay2 文件系统中,这部分空间依旧在旧的层中,占用镜像空间。
docker commit 会完整保留容器的层结构,而不是自动合并或精简
也就是说:
- 每次对容器的变更都会成为新的一层
- 哪怕后来你删除了文件,旧层依然存在
- 最终 commit 镜像会包含所有层的总大小
如何验证?
可以运行以下命令来查容器文件系统真实占用情况(包括已删除文件):
lsof | grep deleted
这会列出仍被某些进程占用、但实际上已经被 rm 掉的文件 这些文件的空间仍然占着,会被 Docker commit 进镜像!
4.解决办法
使用 docker export + import
docker export <your_container_id> -o file_name.tar
docker export e8bb6fd8875f -o /data/plate/zip_tar/handwrite_v2.0.tar
docker export 是导出容器的文件系统内容,包括容器内部所有的文件和目录(不包括挂载的外部卷数据)。它会将容器的文件系统打包成一个 tar 归档文件。
docker import /data/handwrite_v2.0.tar handwrite:v2.0
- 这是 Docker 的一个命令,用于从一个 tar 包(归档文件)导入文件系统快照,创建成一个新的镜像。
- 该 tar 包通常是通过
docker export导出的容器文件系统快照,或者由其他方式打包的 Linux 文件系统。 - 注意:
docker import只导入文件系统,不会包含 Docker 镜像历史(比如每一层的提交记录),也不会包含镜像元数据(比如环境变量、默认命令等),只相当于从 tar 直接生成一个干净的镜像。
5. save 与 import导出方式区别
docker save 与 docker import 有何不同?
| 方面 | docker export | docker save |
|---|---|---|
| 导出对象 | 容器的当前文件系统 | 镜像(image) |
| 是否包含镜像层历史 | 否 | 是 |
| 包含挂载数据吗 | 否 | 否 |
| 用于 | 重新生成文件系统快照(docker import) | 备份镜像,迁移镜像(docker load) |
| 生成文件大小 | 通常较小,包含运行时修改 | 通常较大,包含完整镜像层 |
| 参数要求 | 容器ID或名字 | 镜像名或镜像ID |
- 如果你想备份当前容器状态,
docker export是首选,但会丢失镜像历史和配置。 - 如果你想备份或迁移镜像,
docker save更合适。
