为啥 docker build 中的 COPY 未检测到更新

Posted

技术标签:

【中文标题】为啥 docker build 中的 COPY 未检测到更新【英文标题】:Why is COPY in docker build not detecting updates为什么 docker build 中的 COPY 未检测到更新 【发布时间】:2017-08-21 17:43:27 【问题描述】:

我在节点应用程序上运行构建,然后使用工件构建 docker 映像。将我的源移动到适当位置的 COPY 命令没有检测到构建后对源文件的更改;它只是使用缓存。

Step 9/12 : COPY server /home/nodejs/app/server ---> Using cache ---> bee2f9334952

我是在 COPY 上做错了什么,还是有办法不缓存特定步骤?

【问题讨论】:

【参考方案1】:

我在Docker documentation:

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

所以,据我所知,缓存应该是无效的。您可以使用--no-cache 命令行选项来确保。如果您使用--no-cache 得到正确的行为,而没有它的行为不正确,那么您就会发现一个错误并应该报告它。

【讨论】:

谢谢,很高兴知道它是如何工作的。我假设修改时间戳记了。【参考方案2】:

这很有趣。我发现COPY 工作,只是看起来不是。

我正在重建映像并重新启动容器,但容器仍在使用旧映像。我不得不删除我的容器,然后当我启动它们时,它们使用了新创建的映像,我可以看到我的更改。

Here is another thread 处理这个更准确的诊断(在我的情况下)。

【讨论】:

非常感谢这篇文章!我也遇到了同样的问题,没有注意到容器的图像 id 与我刚刚构建的最新图像的 id 不同。【参考方案3】:

您可以尝试使用 ADD。它将使副本的缓存无效。不好的一面是它也会使缓存在它之后的其他命令失效。如果您的 ADD 位于最后一步,它应该不会对构建过程产生太大影响。

注意:如果 Dockerfile 的内容已更改,则第一个遇到的 ADD 指令将使 Dockerfile 中的所有后续指令的缓存无效。这包括使 RUN 指令的缓存无效。有关更多信息,请参阅 Dockerfile 最佳实践指南。 https://docs.docker.com/engine/reference/builder/#add

【讨论】:

这也是很好的信息。 这同样适用于 COPY:“如果 的内容发生变化,第一个遇到的 COPY 指令将使 Dockerfile 中所有后续指令的缓存失效。这包括使缓存失效运行指令。有关更多信息,请参阅 Dockerfile 最佳实践指南 - 利用构建缓存。” -- docs.docker.com/engine/reference/builder/#copy【参考方案4】:

对我来说,问题在于我对 Docker 构建输出的解释。我没有意识到不仅缓存了层的最后一个版本,而且还缓存了所有以前的版本。

我正在通过来回更改单个文件来测试缓存失效。第一次修改后,缓存失效OK,但是改回来后,图层是从缓存中取出来的,好像失效逻辑不正常。

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#leverage-build-cache

【讨论】:

【参考方案5】:

有同样的问题。在考虑了@Nick Brady 的帖子(感谢您的建议!)之后,这是我当前的更新程序,似乎运行良好:

svn update --non-interactive --no-auth-cache --username UUU --password PPP
docker build . -f deploy/Dockerfile -t myimage
docker stop mycontainer
docker rm mycontainer
docker run --name=mycontainer -p 80:3100 -d --restart=always \
    --env-file=deploy/.env.production myimage

这里的魔力不是简单地重新启动容器 (docker restart mycontainer),因为这实际上会停止并再次运行从先前版本的 myimage 实例化的旧容器。停止并销毁旧容器并运行新容器会导致从新建的myimage 实例化一个新容器。

【讨论】:

【参考方案6】:

从 Docker 的角度来看,这就像任何其他命令一样。

Docker 看到 这一行 没有改变,所以它缓存了它。

同样,如果你的 Dockerfile 中有 curl 命令,Docker 不会获取 URL 只是为了在它发生更改时进行更改。它检查命令是否改变,而不是结果。

【讨论】:

以上是关于为啥 docker build 中的 COPY 未检测到更新的主要内容,如果未能解决你的问题,请参考以下文章

42-Docker-Docker命令详解-docker build

为啥 COPY package*.json ./ 在 COPY 之前。 .?

为啥 docker-compose build 没有给我这样的文件或目录错误消息

使用docker build输出信息

为啥未设置 DBUS_SESSION_BUS_ADDRESS 时 g_file_copy 返回 Operation not supported

ant过滤 - 如果未设置属性,则失败