我很惊讶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
创建了一个新图层?
答案 0 :(得分:28)
在Dockerfile best practices build cache部分详细解释了构建缓存过程。
从缓存中已有的基本映像开始,将下一条指令与从中导出的所有子映像进行比较 基本图像,以查看其中一个是否使用完全相同的构建 指令。如果不是,则缓存无效。
在大多数情况下,只需将
Dockerfile
中的指令与其中一个子图像进行比较即可。但是,确定 说明需要更多的检查和解释。对于
ADD
和COPY
指令,将检查图像中文件的内容,并为每个文件计算校验和。 文件的最后修改时间和最后访问时间不是 在这些校验和中考虑。在缓存查找期间,校验和 与现有图像中的校验和进行比较。如果有什么 已更改文件,如内容和元数据,然后 缓存无效。除
ADD
和COPY
命令外,缓存检查不会查看容器中的文件以确定缓存匹配。对于 例如,处理RUN apt-get -y update
命令时的文件 不会检查容器中更新以确定是否存在缓存 命中存在。在这种情况下,只使用命令字符串本身 找到一个匹配。缓存无效后,所有后续
Dockerfile
命令 将生成新图像,不会使用缓存。
您将遇到操作系统程序包,NPM程序包或Git仓库更新为较新版本(例如~2.3
中的package.json
个semver)但作为Dockerfile
或{{ 1}}没有更新,docker将继续使用缓存。
可以以编程方式生成package.json
,通过修改某些更智能检查上的行来破坏缓存(例如,从repo中检索最新的git branch shasum以在clone指令中使用)。您还可以使用Dockerfile
定期运行构建以强制执行更新。
答案 1 :(得分:5)
这是因为您的package.json
文件已被修改,请参阅Removing intermediate container
。
这通常也是COPY
期间包裹管理器(供应商/第三方)信息文件首先docker build
的原因。之后,您运行包管理器安装,然后添加应用程序的其余部分,即src
。
如果您的lib没有变化,这些步骤将从构建缓存中提供。