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

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

由于 Dockerfile 指令的当前顺序,构建器必须再次下载 Go 模块,尽管自上次以来没有任何包发生更改。
更改指令顺序
您可以通过重新排序 Dockerfile 中的指令来避免这种冗余。 更改指令的顺序,以便在将源代码复制到容器之前下载和安装依赖项。
这样,即使您对源代码进行了更改,构建器也可以重用缓存中的 依赖项
层。
Go 使用两个文件(名为go.mod
和go.sum
)来跟踪项目的依赖项。
这些文件对于 Go 来说,就像package.json
和package-lock.json
对于 JavaScript 来说一样。
为了让 Go 知道要下载哪些依赖项,您需要将go.mod
和go.sum
文件复制到容器中。
在RUN go mod download
之前添加另一个COPY
指令,这次仅复制go.mod
和go.sum
文件。
# syntax=docker/dockerfile:1 FROM golang:1.20-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 指令可以帮助您避免在构建时进行不必要的工作。
相关信息:
接下来
下一节将展示如何使用多阶段构建使构建运行得更快,并使生成的输出更小。