为什么使用--squash参数执行docker build会生成中间镜像?
docker build --squash 运行逻辑与中间悬空镜像的来源 核心执行流程
- 构建初始阶段和不加
--squash的逻辑完全一致:按照Dockerfile的指令逐行执行,生成包含完整多层结构的临时镜像,过程中的缓存规则、层生成逻辑和普通构建没有任何区别。 - 触发层级合并:不会直接把这个生成好的多层临时镜像当作最终结果打标签,而是提取这个临时镜像相对于基础父镜像的所有文件系统差异(包括新增、修改、删除的文件),把这些差异打包成一个独立的、没有多余嵌套层的全新单层镜像。
- 绑定目标标签:将用户指定的标签(比如你的
nvidia-squash:latest)指向这个新生成的单层合并镜像。
那个无标签镜像的由来
- 你看到的ID为66154f6a6cd4的
<none>:<none>镜像,就是上面流程第一步生成的多层结构临时构建产物。等合并后的单层镜像生成、拿到正式标签后,这个原始的多层临时镜像就没有任何标签指向它,成了悬空(dangling)镜像,会默认出现在docker images的输出列表里。 - 这个悬空镜像不会额外重复占用磁盘空间:Docker是分层共享存储的,它和最终的squash镜像、普通构建的
nvidia镜像,底层都共享了NVIDIA父镜像里的大体积只读文件层,这也是为啥三个镜像都显示9.31GB——这个数字只是元数据层面的大小统计,不是实际的磁盘占用量。
为啥squash前后镜像大小完全没差
- squash操作本身不会清理、删除镜像里的任何文件,仅做层级的合并,不会对文件内容做额外压缩。
- 从你的场景来看,整个Dockerfile的操作并没有删除NVIDIA基础镜像里的大体积文件,所有变更只是在原有层基础上做了少量修改,合并为单层之后,总文件体积和原来多层结构的镜像完全一致。
- 大家常说squash能减小镜像体积,对应的是存在跨层删除操作的构建场景(比如先下载大体积安装包、装完之后再删安装包):多层结构下,被上层删除的安装包依然会残留在下层镜像里,只有squash合并后,才会真正把这类跨层删除的文件从最终镜像的文件系统里剔除。你的构建没有这类操作,自然观察不到体积差异。
内容的提问来源于stack exchange,提问作者RafaelJan
相关产品推荐
相关产品推荐

