Docker镜像瘦身

82次阅读
没有评论

共计 1430 个字符,预计需要花费 4 分钟才能阅读完成。

Docker 镜像瘦身

问题

我们在制作 Docker 镜像时,可以不从 Dockfile 进行构建,而是从一个基础镜像启动一个容器,登录该容器,进行一些初始化环境的操作,比如创建文件,删除文件等,最后将该容器提交为一个镜像。最后,发现制作出来的镜像体积很大,如何对该镜像进行瘦身呢?

原理

在给出具体方案前,先介绍下 Docker 的原理。Docker 使用存储驱动程序来存储镜像层和容器的可写层。

存储驱动程序针对空间效率进行了优化,但写入速度还是低于本机文件系统性能。

Dockerfile 中的 FROM 和 RUN 的行都会生成层,无论是生成文件或删除文件,都会产生新的层。这些层是 只读的,随着 Dockerfile 的增加,后边的层依赖前面的层,堆叠在一起。

镜像的大小,就是每层累积起来的大小,而镜像的每一层都是 只读层。最后的 CMD 表示在容器里运行的指令,是不会在镜像中产生层的。

容器和镜像之间的主要区别在于顶层可写层。当创建一个新容器时,会在镜像的层基础上,增加一个可写层(通常被称为“容器层”)。对正在运行的容器所做的所有更改,例如写入新文件、修改现有文件和删除文件,都将写入这个薄的可写容器层(Thin R/W layer)。当容器被删除时,可写层也被删除。

因为每个容器都有自己的可写容器层,所以多个容器可以共享对同一底层镜像的访问,但保持有自己的数据状态。如下图所示:

Docker 镜像瘦身

写时复制 (CoW) 是一种高效的共享 / 复制文件策略。如果一个文件或目录存在于镜像中的较低层,而另一更高层(包括可写层)需要对其进行读取访问时:文件被从低层复制到高层并进行修改。这最大限度地减少了 I/O 和每个后续层的大小。

裁剪现有镜像

回到最初的问题,当我们通过容器对初始化环境完成后,通过 docker commit {container id} 将容器打包成镜像,然后,通过 docker tag {image id} {tag} 对新制作的镜像打 tag。然后,通过 docker inspect {tag} 查看到新制作出来的镜像是两层,整个镜像的大小是两层的累积。例如 hadoop 3.3.5 使用 docker 编译源码 制作出来的 tag 为suizhe007/hadoop:v3.3.5.1 镜像为 11.8GB,运行命令docker inspect suizhe007/hadoop:v3.3.5.1,结果下图所示:

Docker 镜像瘦身

如何裁剪瘦身呢?

原理上一节已经介绍过了,我们首先将镜像中的缓存文件和中间文件等删除掉,然后将 Layer 合并为一个,就达到了镜像瘦身的目的。具体做法如下:

首先将该镜像 suizhe007/hadoop:v3.3.5.1 以容器方式启动,运行如下命令:

docker run -i -t suizhe007/hadoop:v3.3.5.1

裁剪现有镜像需要使用 docker export + docker import 将容器的状态,导出成一层然后导入,这样删除起作用了。本质上是 通过丢弃层累积的信息 来实现的。

导出命令如下:

 docker export 1bd5f87e > hadoop3-v1.tar

导入容器 tar 文件,得到 单层 镜像,导入命令如下:

 docker import hadoop3-v1.tar

如下图所示,得到的 suizhe007/hadoop:v3.3.5.2 大小仅为 2.86GB,大大缩减镜像的大小:

Docker 镜像瘦身

后记

相信通过本文,你已经对 docker 镜像和容器的原理有所了解,以及对现有体积巨大的容器如何瘦身也有一定的优化思路,关于更深入的 docker 方面的知识,后续还会继续分享。

正文完
 0
醉酒的行者
版权声明:本站原创文章,由 醉酒的行者 于2024-08-15发表,共计1430字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)