构建缓存失效

在构建镜像时,Docker 会按照您在 Dockerfile 中指定的顺序逐步执行每条指令。对于每条指令,构建器 都会检查是否可以重用构建缓存中的该指令。

通用规则

构建缓存失效的基本规则如下:

  • 构建器首先检查基础镜像是否已缓存。随后的每条指令都会与缓存的层进行比较。如果没有缓存的层与指令完全匹配,则缓存将被使无效。

  • 在大多数情况下,将 Dockerfile 指令与相应的缓存层进行比较就足够了。但是,某些指令需要额外的检查和说明。

  • 对于ADDCOPY指令,以及具有绑定挂载的RUN指令(RUN --mount=type=bind),构建器会从文件元数据计算缓存校验和,以确定缓存是否有效。在缓存查找期间,如果参与的任何文件的文件元数据已更改,则会使缓存失效。

    文件的修改时间(mtime)在计算缓存校验和时不会被考虑。如果只是复制的文件的mtime发生了变化,缓存不会被使无效。

  • ADDCOPY命令外,缓存检查不会查看容器中的文件以确定缓存匹配。例如,在处理RUN apt-get -y update命令时,不会检查容器中更新的文件以确定是否存在缓存命中。在这种情况下,仅使用命令字符串本身来查找匹配项。

一旦缓存被使失效,后续的所有Dockerfile命令都会生成新的镜像,且不会使用缓存。

如果你的构建包含多个层,并且你希望确保构建缓存可重用,请尽可能将指令从不常更改到更常更改的顺序排列。

运行指令

构建之间不会自动使 RUN 指令的缓存失效。 假设你的 Dockerfile 中有一个步骤用于安装 curl

FROM alpine:3.21 AS install
RUN apk add curl

这并不意味着镜像中的版本curl始终是最新的。 一周后重新构建镜像仍将获得与之前相同的软件包。 要强制重新执行RUN指令,您可以:

  • 确保在它之前的层已更改
  • 在构建前清除构建缓存,使用 docker builder prune
  • 使用 --no-cache--no-cache-filter 选项

--no-cache-filter 选项允许您指定要使缓存失效的特定构建阶段:

$ docker build --no-cache-filter install .

构建密钥

构建机密的内容不属于构建缓存。 更改机密的值不会导致缓存失效。

如果您在更改机密值后想强制缓存失效, 可以在更改机密时更改一个任意值的构建参数来传递。 构建参数确实会导致缓存失效。

FROM alpine
ARG CACHEBUST
RUN --mount=type=secret,id=TOKEN,env=TOKEN \
    some-command ...
$ TOKEN="tkn_pat123456" docker build --secret id=TOKEN --build-arg CACHEBUST=1 .

机密的属性,如ID和挂载路径,都参与缓存校验和,如果更改会导致缓存失效。