参考:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#from
用 .dockerignore 排除
要排除与构建无关的文件(不重组源存储库),请使用.dockerignore
文件。此文件支持类似于.gitignore
文件的排除模式。有关创建一个的信息,请参阅 .dockerignore 文件。
使用多阶段构建
多阶段构建允许您大幅减少最终图像的大小,而无需费力减少中间层和文件的数量。
因为镜像是在构建过程的最后阶段构建的,所以您可以通过利用构建缓存来最小化镜像层。
例如,如果您的构建包含多个层,您可以将它们从更改较不频繁(以确保构建缓存可重用)到更改较频繁的排序:
安装构建应用程序所需的工具
安装或更新库依赖项
生成您的应用程序
不要安装不必要的包
为了减少复杂性、依赖性、文件大小和构建时间,避免安装额外或不必要的包,因为它们可能“很好”。例如,您不需要在数据库图像中包含文本编辑器。
解耦应用程序
每个容器应该只有一个关注点。将应用程序解耦到多个容器中,可以更轻松地进行水平扩展和重用容器。例如,Web 应用程序堆栈可能由三个独立的容器组成,每个容器都有自己独特的映像,以分离的方式管理 Web 应用程序、数据库和内存缓存。
将每个容器限制为一个进程是一个很好的经验法则,但这不是一个硬性规定。例如,不仅容器可以 通过 init 进程产生,一些程序可能会自行产生额外的进程。例如,Celery可以产生多个工作进程,而Apache可以为每个请求创建一个进程。
使用您的最佳判断力使容器尽可能保持清洁和模块化。如果容器之间相互依赖,可以使用Docker容器网络 来保证这些容器之间可以通信。
尽量减少层数
在旧版本的 Docker 中,尽量减少镜像中的层数以确保它们的性能非常重要。添加了以下功能以减少此限制:
只有说明
RUN
,COPY
,ADD
创建图层。其他指令会创建临时中间映像,并且不会增加构建的大小。在可能的情况下,使用多阶段构建,并且只将您需要的工件复制到最终映像中。这允许您在中间构建阶段包含工具和调试信息,而不会增加最终映像的大小。
对多行参数进行排序
只要有可能,通过按字母数字顺序对多行参数进行排序来简化以后的更改。这有助于避免包重复并使列表更易于更新。这也使 PR 更易于阅读和审查。在反斜杠 ( \
)前添加一个空格也有帮助。
利用构建缓存
构建映像时,Docker 会逐步 Dockerfile
执行 中的说明,并按照指定的顺序执行每个说明。在检查每条指令时,Docker 会在其缓存中查找可以重用的现有映像,而不是创建新的(重复)映像。
如果您根本不想使用缓存,则可以使用命令--no-cache=true
上的选项docker build
。但是,如果您确实让 Docker 使用其缓存,那么了解它什么时候可以,什么时候不能找到匹配的图像很重要。Docker 遵循的基本规则概述如下:
从已经在缓存中的父映像开始,下一条指令与从该基本映像派生的所有子映像进行比较,以查看其中一个是否是使用完全相同的指令构建的。如果不是,则缓存无效。
在大多数情况下,简单地将 中的指令
Dockerfile
与子图像之一进行比较就足够了。但是,某些说明需要更多的检查和解释。对于
ADD
和COPY
指令,检查图像中文件的内容并为每个文件计算校验和。这些校验和不考虑文件的最后修改和最后访问时间。在缓存查找期间,校验和与现有图像中的校验和进行比较。如果文件中的任何内容(例如内容和元数据)发生了更改,则缓存将失效。除了
ADD
andCOPY
命令之外,缓存检查不会查看容器中的文件来确定缓存匹配。例如,在处理RUN apt-get -y update
命令时,不会检查容器中更新的文件以确定是否存在缓存命中。在这种情况下,仅使用命令字符串本身来查找匹配项。
一旦缓存失效,所有后续Dockerfile
命令都会生成新图像,并且不会使用缓存。
使用管道
某些RUN命令依赖于使用管道字符 ( |)将一个命令的输出通过管道传输到另一个命令的能力,如下例所示:
RUN wget -O - https://some.site | wc -l > /number
Docker 使用/bin/sh -c解释器执行这些命令,它只评估管道中最后一个操作的退出代码来确定成功。在上面的示例中,只要wc -l命令成功,即使wget命令失败,此构建步骤也会成功并生成新映像。
如果您希望命令因管道中任何阶段的错误而失败,请预先添加set -o pipefail &&以确保意外错误防止构建意外成功。例如:
RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
并非所有 shell 都支持该-o pipefail选项。
在dash基于 Debian 的映像上的shell 等情况下,请考虑使用exec形式RUN明确选择支持该pipefail选项的 shell 。例如:
RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
CMD
该CMD
指令应用于运行image中包含的软件以及任何参数。CMD
应该几乎总是以 下的形式使用CMD ["executable", "param1", "param2"…]
。因此,如果image用于服务,例如 Apache 和 Rails,您将运行类似CMD ["apache2","-DFOREGROUND"]
. 实际上,对于任何基于服务的image,都推荐使用这种形式的指令。