06 | 编写最优Dockerfile
生产实践中一定优先使用 Dockerfile 的方式构建镜像。 因为使用 Dockerfile 构建镜像可以带来很多好处:
-
易于版本化管理,Dockerfile 本身是一个文本文件,方便存放在代码仓库做版本管理,可以很方便地找到各个版本之间的变更历史;
-
过程可追溯,Dockerfile 的每一行指令代表一个镜像层,根据 Dockerfile 的内容即可很明确地查看镜像的完整构建过程;
-
屏蔽构建环境异构,使用 Dockerfile 构建镜像无须考虑构建环境,基于相同 Dockerfile 无论在哪里运行,构建结果都一致。
虽然有这么多好处,但是如果你 Dockerfile 使用不当也会引发很多问题。比如镜像构建时间过长,甚至镜像构建失败;镜像层数过多,导致镜像文件过大。
Dockerfile书写原则
(1)单一职责
由于容器的本质是进程,一个容器代表一个进程,因此不同功能的应用应该尽量拆分为不同的容器,每个容器只负责单一业务进程。
(2)提供注释信息
Dockerfile也是一种代码,我们应该保持良好的代码编写习惯。
(3)保持容器最小化
避免安装无用的软件包,比如在一个nginx镜像中,我并不需要安装vim、gcc等开发便以工具。这样不仅可以加快容器构建速度,而且可以避免镜像体积过大。
(4)合理选择基础镜像
容器的核心是应用,因此只要基础镜像能满足应用的运行环境即可。如一个Java类型的应用运行时只需要JRE,并不需要JDK,因此镜像只需要安装JRE环境即可。
(5)使用.dockerignore文件
在使用git时,我们可以使用.gitignore文件忽略一些不需要做版本管理的软件。同理,使用.dockerignore文件允许我们在构建时,忽略一些不需要参与构建的文件,从而提升构建的效率。.dockerignore的定义类似于.gitignore。
.dockerignore的本质是文本文件,docker构建时可以使用换行符来解析文件定义,每一行忽略一些文件或者文件夹。具体使用方式如下:
(6)尽量使用构建缓存
Docker在构建过程中,每一条Dockerfile指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。如果构建时发现要构建的镜像层的父镜像层已经存在,并且下一条命令使用了相同的指令,即可命中构建缓存。
Docker 构建时判断是否需要使用缓存的规则如下:
从当前构建层开始,比较所