Docker如何知道在构建过程中何时使用缓存以及何时不使用缓存



我很惊讶Docker对层的缓存效果有多好,但我也想知道它是如何决定是否使用缓存层的。

让我们以以下构建步骤为例:

Step 4 : RUN npm install -g   node-gyp
 ---> Using cache
 ---> 3fc59f47f6aa
Step 5 : WORKDIR /src
 ---> Using cache
 ---> 5c6956ba5856
Step 6 : COPY package.json .
 ---> d82099966d6a
Removing intermediate container eb7ecb8d3ec7
Step 7 : RUN npm install
 ---> Running in b960cf0fdd0a

例如,它如何知道可以为npm install -g node-gyp使用缓存层,但为npm install创建新层?

构建缓存过程在编写Dockerfiles:Leverage构建缓存部分的最佳实践中得到了相当全面的解释。

  • 从已经在缓存中的父映像开始,将下一条指令与从该基本映像派生的所有子映像进行比较,以查看其中一个映像是否使用完全相同的指令构建。否则,缓存将无效。

  • 在大多数情况下,简单地将Dockerfile中的指令与其中一个子图像进行比较就足够了。然而,某些说明需要更多的检查和解释。

  • 对于ADDCOPY指令,检查图像中文件的内容,并为每个文件计算校验和。在这些校验和中不考虑文件的最后修改和最后访问时间。在高速缓存查找过程中,将校验和与现有映像中的校验和进行比较。如果文件中有任何更改,例如内容和元数据,则缓存将无效。

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

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

你会遇到这样的情况:操作系统包、NPM包或Git回购被更新到新版本(比如package.json中的~2.3 semver),但由于你的Dockerfilepackage.json尚未更新,docker将继续使用缓存。

可以通过编程生成Dockerfile,通过修改某些智能检查的行来破坏缓存(例如,从repo中检索最新的git分支shasum以用于克隆指令)。您还可以定期使用--no-cache=true运行构建以强制执行更新。

这是因为您的package.json文件已被修改,请参阅Removing intermediate container

这通常也是包管理器(供应商/第三方)信息文件在docker build期间首先被COPY的原因。之后,您运行包管理器安装,然后添加应用程序的其余部分,即src

如果您的libs没有更改,那么这些步骤将从构建缓存中提供。

最新更新