引言

这是有关如何制作最小化Docker镜像的第二篇文章,在之前的文章中,我谈到了如何创建最小化的Docker镜像,但是可以制作镜像的大小其实是有限制的,我概述了一种使添加到Docker镜像中的layer层变小的方法,但有时可能无法做到,也许需要按照特定的顺序运行一些额外的步骤。
比如下面这个例子,需要在中间的步骤中添加一个文件:

RUN ...
ADD some_file /
RUN ...

如果我需要在添加文件之前在第一个RUN命令中进行一些处理,然后在第二个RUN命令中进行一些清理之前进行更多处理,该怎么办? 在这种情况下,很不走运的是,Docker将在每个命令之后创建一个layer层,而且可能还会遇到以下棘手的情况:要使用的基础镜像继承自许多其他镜像,并且每个镜像都添加了自己很大的layer层。

Docker Squash

Docker没有提供一种将运行的命令与layer层缓存分离的方法,理论上这可以做到,但这会导致镜像过大。 为了减少层的数量及其大小,可以像压缩git commit一样压缩layer层。 有一个非常酷的工具称为docker-squash可以执行此操作, 您可以在作者的原始文章中了解有关此内容的更多信息。
image.png

Docker squash将压缩多个镜像layer层,以便删除存储在中间步骤中的所有数据,当遇到上述情况时,这真的很棒,或者说如果你想让Dockerfile变得不那么复杂,就去试一试吧。

Squashing Python

我想看看是否可以缩小docker hub上的标准python:2.7.11图像,从Dockerfile中注意到,首先要清除当前安装的Debian python,然后再下载并编译自己的版本。 但是,由于Debian python已包含在较早的一层中,因此该空间已被我们的镜像占用,这些镜像还取决于其他几个Dockerfile,每个Dockerfile都添加了自己的层。 让我们看看通过squashing可以节省多少空间。

首先将python:2.7.11的镜像pull到本地

$ docker pull python:2.7.11
2.7.11: Pulling from library/python
7a01cc5f27b1: Pull complete 
3842411e5c4c: Pull complete 
...
127e6c8b9452: Pull complete 
88690041a8a3: Pull complete 
Digest: sha256:590ee32a8cab49d2e7aaa92513e40a61abc46a81e5fdce678ea74e6d26e574b9
Status: Downloaded newer image for python:2.7.11

可以看到该镜像具有很多层,大小约为676MB。

$ docker images python:2.7.11
REPOSITORY          TAG                 IMAGE ID            CREATED
VIRTUAL SIZE
python              2.7.11              88690041a8a3        2 weeks ago
676.1 MB

docker-squash不允许压缩本地镜像仓库中的镜像,这点令人讨厌。 相反,它要求将镜像导出为文件,接下来继续操作,并创建一个新的squashed镜像。

$ docker save python:2.7.11 > python-2.7.11.tar
$ sudo bin/docker-squash -i python-2.7.11.tar -o python-squashed-2.7.11.tar

现在可以看到新文件缩小了约75MB。

~$ ls -lh python-*.tar
-rw-rw-r-- 1 ian  ian  666M Feb 15 16:32 python-2.7.11.tar
-rw-r--r-- 1 root root 590M Feb 15 16:33 python-squashed-2.7.11.tar

在将其重新加载到本地镜像仓库中之后,再次查看镜像大小发现小了很多:

$ cat python-squashed-2.7.11.tar | docker load
$ docker images python-squashed
REPOSITORY          TAG                 IMAGE ID            CREATED
VIRTUAL SIZE
python-squashed     latest              18d8ebf067fd        11 days ago
599.9 MB

Virtual Size

你会注意到,尽管docker向我们显示了镜像的“虚拟大小”,那是因为Docker重用了依赖于相同层的镜像,就像git commit的方式以及修改或squashing提交的方式一样,这是一个全新的提交方式,docker-squash将创建一个包含所有内容的全新的独立层。

Docker-squash允许你通过提供-from参数来处理这种情况,此参数的默认值是第一个FROM层。 上面的情况是这样,因为有许多FROM层,所以它能够压缩掉一些不必要的数据,但仍从基础镜像离开该层,通过指定此参数,可以决定要使用哪个基础镜像,这样就不必每次都去下载。

$ docker-squash -from 18d8ebf067fd -i ... -o ...

Docker-squash不是万能药,但确实为你的工具箱添加了一个工具用于管理Docker镜像大小。在接下来的两篇文章中,我将讨论一些其他工具和方法来减小Docker镜像的大小。


EngineerLeo
598 声望38 粉丝

专注于云原生、AI等相关技术