我很惊讶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
Run Code Online (Sandbox Code Playgroud)
例如,它如何知道它可以使用缓存层npm install -g node-gyp
但为其创建一个新层npm install
?
Mat*_*att 36
在Dockerfile最佳实践构建缓存部分中详细解释了构建缓存过程.
从已经在高速缓存中的基础图像开始,将下一条指令与从该基础图像导出的所有子图像进行比较,以查看它们中的一个是否使用完全相同的指令构建.如果不是,则缓存无效.
在大多数情况下,简单地比较
Dockerfile
一个子图像中的指令就足够了.但是,某些说明需要更多的检查和解释.对于
ADD
和COPY
指令,检查图像中文件的内容,并计算每个文件的校验和.在这些校验和中不考虑文件的最后修改时间和最后访问时间.在高速缓存查找期间,将校验和与现有映像中的校验和进行比较.如果文件中的任何内容(例如内容和元数据)发生了任何更改,则缓存将失效.除了
ADD
和COPY
命令之外,缓存检查不会查看容器中的文件来确定缓存匹配.例如,在处理RUN apt-get -y update
命令时,将不检查容器中更新的文件以确定是否存在缓存命中.在这种情况下,命令字符串本身将用于查找匹配项.缓存无效后,所有后续
Dockerfile
命令都将生成新映像,并且不会使用缓存.
您将遇到操作系统软件包,NPM软件包或Git存储库更新到较新版本(例如~2.3
semver package.json
)的情况,但是当您Dockerfile
或未package.json
更新时,docker将继续使用缓存.
Dockerfile
通过修改某些更智能的检查上的行(例如,从repo中检索最新的git branch shasum以在clone指令中使用),可以以编程方式生成破坏缓存的内容.您还可以定期运行构建--no-cache=true
以强制执行更新.
这是因为您的package.json
文件已被修改,请参见Removing intermediate container
。
这通常也是COPY
在期间首先编辑软件包管理器(供应商/第三方)信息文件的原因docker build
。之后,您将运行软件包管理器安装,然后添加其余的应用程序,即src
。
如果您的库没有任何更改,则从构建缓存执行这些步骤。