层数
Dockerfile 指令的顺序很重要。 Docker 构建由一系列有序的构建指令组成。 Dockerfile 中的每条指令大致翻译为一个镜像层。下图说明了 Dockerfile 如何转换为容器映像中的层堆栈。


缓存层
当您运行构建时,构建器会尝试重用早期构建中的层。如果图像的某个图层未更改,则构建器会从构建缓存中选取它。如果自上次构建以来某个层发生了更改,则必须重新构建该层以及后续的所有层。
上一节中的 Dockerfile 将所有项目文件复制到容器 ( COPY . .
),然后在以下步骤 ( RUN go mod download
) 中下载应用程序依赖项。如果您要更改任何项目文件,那么该层的缓存就会失效COPY
。它还会使后续所有层的缓存失效。


由于 Dockerfile 指令的当前顺序,构建器必须再次下载 Go 模块,尽管自上次以来没有任何包发生更改。
更新指令顺序
您可以通过重新排序 Dockerfile 中的指令来避免这种冗余。更改指令的顺序,以便在将源代码复制到容器之前下载和安装依赖项。这样,即使您对源代码进行了更改,构建器也可以重用缓存中的“依赖项”层。
Go 使用两个文件(名为go.mod
和go.sum
)来跟踪项目的依赖关系。这些文件是 Go 的文件,whatpackage.json
是package-lock.json
JavaScript 的文件。为了让 Go 知道要下载哪些依赖项,您需要将go.mod
和
go.sum
文件复制到容器中。在 之前添加另一COPY
条指令
RUN go mod download
,这次仅复制go.mod
和go.sum
文件。
# syntax=docker/dockerfile:1
FROM golang:1.21-alpine
WORKDIR /src
- COPY . .
+ COPY go.mod go.sum .
RUN go mod download
+ COPY . .
RUN go build -o /bin/client ./cmd/client
RUN go build -o /bin/server ./cmd/server
ENTRYPOINT [ "/bin/server" ]
现在,如果您编辑源代码,构建映像将不会导致构建器每次都下载依赖项。该COPY . .
指令出现在包管理指令之后,因此构建器可以重用该
RUN go mod download
层。


概括
适当地排序 Dockerfile 指令可以帮助您避免构建时不必要的工作。
相关信息:
下一步
下一节将展示如何使用多阶段构建使构建运行得更快,并使生成的输出更小。