执行docker load加载tar包时如何保留原有镜像层不被合并?
首先先澄清一个认知误区:你看到docker image history显示<missing>并不代表镜像层被合并,所有层实际都完整存在(镜像可以正常运行就可以证明这点),只是19.03版本的Docker默认不会将父层、中间层的元数据单独打包到单镜像的save导出包中,本地缺少对应层的镜像ID记录才会显示<missing>。
针对你使用的19.03.15版本,有两种可行方案实现导入后无<missing>的分层展示:
方案1:导出镜像时将所有关联的父镜像、中间镜像一起打包
你示例中用到的基础镜像是ubuntu:20.04,执行save命令时把基础镜像和业务镜像一起导出即可:docker save -o out.tar ubuntu:20.04 test:test导入该tar包时会同时加载基础镜像和所有中间层的元数据,
docker history即可展示完整的分层记录。
如果你的镜像存在未被清理的build中间层,也可以把对应中间镜像ID一同加到save命令的参数列表中。方案2:build镜像时关闭自动清理中间层的配置
执行build命令时添加--rm=false参数,禁止Docker build完成后自动删除中间镜像:docker build --rm=false -t test:test .之后save导出时把所有生成的中间镜像一同打包,导入后也可以保留完整分层显示。
如果可以升级Docker版本,直接升级到20.10及以上版本即可彻底解决该问题:20.10版本开始优化了docker save的打包逻辑,单镜像导出时会自带所有层的元数据信息,不需要额外打包父镜像,load导入后默认就可以显示完整的分层历史,无<missing>记录。
可以通过以下命令验证分层是否真的合并:导入前后分别执行docker inspect test:test | jq .[0].RootFS.Layers | length,输出的层数完全一致即可证明没有发生层合并,仅为展示问题。
内容的提问来源于stack exchange,提问作者Doz Parp

