编写 Dockerfile 的一般最佳实践
使用多阶段构建
多阶段构建可让您通过在图像构建和最终输出之间创建更清晰的分离来减小最终图像的大小。将 Dockerfile 指令拆分为不同的阶段,以确保生成的输出仅包含运行应用程序所需的文件。
使用多个阶段还可以通过并行执行构建步骤来更有效地构建。
有关更多信息,请参阅 多阶段构建。
使用 .dockerignore 排除
要排除与构建无关的文件,而不重构源存储库,请使用.dockerignore
文件。该文件支持与.gitignore
文件类似的排除模式。有关创建一个的信息,请参阅
Dockerignore 文件。
创建临时容器
Dockerfile 定义的镜像应该生成尽可能短暂的容器。短暂意味着容器可以被停止和销毁,然后用绝对最小的设置和配置重建和替换。
请参阅 十二要素应用程序方法论下的进程 ,了解以这种无状态方式运行容器的动机。
不要安装不必要的包
避免仅仅因为拥有它们可能会更好而安装额外或不必要的软件包。例如,您不需要在数据库图像中包含文本编辑器。
当您避免安装额外或不必要的软件包时,您的映像就会降低复杂性、减少依赖性、减小文件大小并缩短构建时间。
解耦应用程序
每个容器应该只有一个关注点。将应用程序解耦到多个容器中可以更轻松地水平扩展和重用容器。例如,Web 应用程序堆栈可能由三个独立的容器组成,每个容器都有自己独特的映像,以解耦的方式管理 Web 应用程序、数据库和内存缓存。
将每个容器限制为一个进程是一个很好的经验法则,但这并不是一个硬性规定。例如,不仅可以 使用 init 进程生成容器,某些程序还可能自行生成其他进程。例如, Celery可以生成多个工作进程,而 Apache可以为每个请求创建一个进程。
运用您的最佳判断力,尽可能保持容器清洁和模块化。如果容器之间相互依赖,可以使用Docker容器网络 来确保这些容器可以通信。
对多行参数进行排序
只要有可能,请按字母数字对多行参数进行排序,以便于维护。这有助于避免重复的包并使列表更容易更新。这也使得 PR 更容易阅读和审查。在反斜杠 ( ) 之前添加空格\
也有帮助。
以下是buildpack-deps 图像中的示例 :
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion \
&& rm -rf /var/lib/apt/lists/*
利用构建缓存
构建镜像时,Docker 将逐步执行 Dockerfile 中的指令,并按照指定的顺序执行每个指令。对于每条指令,Docker 都会检查是否可以重用构建缓存中的指令。
了解构建缓存的工作原理以及缓存失效的发生方式对于确保更快的构建至关重要。有关 Docker 构建缓存以及如何优化构建的更多信息,请参阅 Docker 构建缓存。
固定基础镜像版本
图像标签是可变的,这意味着发布者可以更新标签以指向新图像。这很有用,因为它允许发布者更新标签以指向图像的较新版本。作为镜像消费者,这意味着您在重新构建镜像时会自动获取新版本。
例如,如果您FROM alpine:3.19
在 Dockerfile 中指定,3.19
则解析为3.19
.
# syntax=docker/dockerfile:1
FROM alpine:3.19
在某个时间点,3.19
标签可能指向镜像的版本 3.19.1。如果您在 3 个月后重建镜像,相同的标签可能会指向不同的版本,例如 3.19.4。此发布工作流程是最佳实践,大多数发布商都使用此标记策略,但并未强制执行。
这样做的缺点是,不能保证每次构建都会得到相同的结果。这可能会导致重大更改,并且意味着您也无法对正在使用的确切映像版本进行审核跟踪。
为了完全确保供应链的完整性,您可以将映像版本固定到特定的摘要。通过将图像固定到摘要,即使发布商用新图像替换标签,也可以保证您始终使用相同的图像版本。例如,以下 Dockerfile 将 Alpine 映像固定到与之前相同的标签,3.19
但这次也带有摘要引用。
# syntax=docker/dockerfile:1
FROM alpine:3.19@sha256:13b7e62e8df80264dbb747995705a986aa530415763a6c58f84a3ca8af9a5bcd
使用此 Dockerfile,即使发布者更新了3.19
标签,您的构建仍将使用固定的映像版本:
13b7e62e8df80264dbb747995705a986aa530415763a6c58f84a3ca8af9a5bcd
。
虽然这可以帮助您避免意外的更改,但每次您想要更新时都必须手动查找并包含基本映像版本的映像摘要,这也更加繁琐。并且您选择退出自动安全修复,这可能是您想要的。
Docker Scout 有一个内置的 过时基础镜像 策略,用于检查您使用的基础镜像版本是否确实是最新版本。此策略还会检查 Dockerfile 中固定的摘要是否对应于正确的版本。如果发布商更新了您已固定的图像,则政策评估会返回不合规状态,指示您应该更新图像。
Docker Scout 还支持自动修复工作流程,使您的基础映像保持最新。当新的镜像摘要可用时,Docker Scout 可以自动在您的存储库上提出拉取请求,以更新您的 Dockerfiles 以使用最新版本。这比使用自动更改版本的标签更好,因为您处于控制之中,并且可以对更改发生的时间和方式进行审计跟踪。
有关使用 Docker Scout 自动更新基础映像的更多信息,请参阅 修复