1 背景
我们在完成一个工程时,普遍会先构建一个基础镜像,然后基于基础镜像打包构建,于是,在发布时,我们需要导出多个镜像(如生产环境没有 harbor 之类的镜像仓库时)。
Transclude of 项目镜像构建.excalidraw
就如这个图里,我们实际需要导出的是Service Image
。
一般情况下,我们导出docker
镜像时,普遍使用save
命令导出镜像:
docker image save {镜像名称}:{TAG} -o image.tar
我们可以一个一个导出,这样看起来是没有什么问题,但我们可能意识到,这样导出来的文件非常大。我们需要知道,docker
镜像是一层一层的layer
堆叠起来的,也就是说,以这种方式导出镜像,每次导出都将基础镜像的所有layer
也导出了一份。
假设我们将上面的Service Image
全部导出,那么Base Image
被导出了 5 次,C++ Image
被导出了 2 次…但实际上我们只需要一份就够了。
2 复用通用层
实际上docker
是允许多个镜像同时导出的,当一次性导出多个镜像到同一个文件时,docker
会每个layer
只保留一个,对于上面的镜像关系来说,假设我们将所有Service Image
导出成一个镜像文件,那么Base Image
、C++ Image
、Java Tomcat Image
、Python Image
也都只会被导出一次,这将大大缩小镜像体积。
事实上实现也非常简单:
docker image save service1:latest service2:latest service3:latest service4:latest service5:latest -o service1-5.tar
此时我们对比一下体积,会发现镜像小了不少。