代码改变世界

原本3GB+ 的 Docker 镜像直接缩成500M

2026-07-01 22:02  AlfredZhao  阅读(5)  评论(0)    收藏  举报

笔者为了给客户提供体积更小的安装介质,使用 docker save 对几组镜像(在机器上加起来有 3.42GB)统一打包后再压缩,最后发现居然只有 500MB 左右,开始还以为是不是漏包了,结果排查发现这不是异常,反而说明这种打包方式是对的。

01 | 先看账面体积为什么会这么大

把这 5 个镜像在本地磁盘上的大小直接相加,大约是:

$$1.19\text{ GB} + 484\text{ MB} + 165\text{ MB} + 282\text{ MB} + 1.33\text{ GB} \approx 3.42\text{ GB}$$

也就是说,从“各自展开后分别占空间”的角度看,它们确实一共占了 3.42GB。

但这个数字只是“死板相加”的结果,并不等于打包后一定也要占这么大。因为 Docker 镜像本身就是按层组织的,统一导出时,重复内容不会傻乎乎地写很多遍。

02 | 为什么统一打包后能缩到 500MB 左右

① 相同基础层只会保留一次

从镜像列表看,像 dataclaw(1.19GB)和 viz-server(1.33GB)这类偏大的后端服务,很可能共享一部分厚重的基础层。

这意味着,当它们一起执行 docker save 时,重叠的那部分基础内容不会重复写入归档包,而是只保留一份。统一打包的价值,首先就体现在这里。

gzip 会继续把可压缩内容压小

镜像里除了基础系统文件,还会包含服务代码、前端静态资源,以及各种依赖包。

这些内容在磁盘上是展开状态,看起来体积很大;但进入 tar 后再经过 gzip 压缩,很多重复文件、重复结构和可压缩的二进制内容都会被进一步缩小。所以,最后从 3.42GB 变成 500MB 左右,并不夸张。

03 | 这份包是否完整

笔者环境中还有一个关键信息:docker.io/library/nginx latest 这张镜像,在之前的 manifest.json 中曾被标成 localhost/nginx:latest

但只要执行 docker save 时写的是 nginx:latest,并且实际已经成功抓到了对应镜像,那么这个名称差异本身不影响结果。它说明镜像已经被正常纳入打包内容。

所以,这个 dataclaw-all-images.tar.gz 体积只有 500MB 左右,并不代表少了东西,反而更像是一份去掉重复层、再经过压缩后的有效交付包。

关注我,和AI一起成长~