如何调试Docker缓存失效?

如何调试Docker缓存失效?

Docker 有一个缓存,这很好,但是我在“docker build”输出中看到的都是:

---> Using cache

或命令的输出(这意味着它没有使用缓存)。

在我的 Dockerfile 中执行完一个步骤(COPY)后,它显然不使用缓存。但我相当确定它正在复制的文件夹中没有任何变化。(这是我们的应用程序,例如,即使我连续部署两次,也会遇到无缓存的情况。)

有没有什么方法可以让 Docker 告诉我它认为发生了哪些变化?

我知道 Docker 曾经检查过时间戳,但是这个问题在 Docker 1.8 中已经修复,现在我使用的是 Docker 1.9.x。

答案1

使用二分查找,带有.dockerignore

将一半文件添加到.dockerignore,然后构建容器。如果它使用缓存执行此COPY步骤,则您知道更改的文件位于您忽略的集合中,否则您知道它位于另一半中。对有更改的文件集重复此测试,直到只有一个文件/文件夹。

(亲爱的 lazyweb:想办法扩展 Docker,让这一切变得不那么痛苦!)

答案2

正如我所讨论的这篇博文我发现 Docker 中(意外的)缓存未命中有以下原因:

  • 如果问题发生在CI 管道,如果你使用多种的构建代理机器(或“临时”机器),可能会发生构建作业 #1 在代理 #A 上执行,但构建作业 #2 在代理 #B 上执行,后者具有与代理 #A 不同的本地缓存。因此,当您查看 CI 管道输出时,请务必检查作业在哪个代理上执行。为了防止此类缓存未命中,您可以使用远程缓存,将缓存信息存储在远程映像注册表中。有两种实现方法:排队缓存(镜像构建器将缓存元数据嵌入到其构建的镜像中),或者使用单独的注册表缓存(推送仅包含缓存 blob 的单独映像)。远程缓存的使用详情取决于您的映像生成器工具。例如,docker build仅支持内联缓存(请参阅这里), docker buildx(或直接使用 BuildKit 时)支持两种方法(参见这里)、Buildah和kaniko仅支持注册表缓存。
  • 如果你ARG在 Dockerfile 中使用,很容易意外破坏缓存失效。每当 some 的值ARG在两次执行之间不同时docker build,第二次执行将无法重用先前缓存的层,用于RUNENV命令,用途的值ARG。这也会使所有后续层无效。请参阅这里了解背景信息。如果您使用多阶段构建,如果你运行docker build 一些次(针对不同的目标), 确保你总是提供相同的阿根廷全部docker build 调用!
  • 有时,每当有新的根据图像已发布(您在FROM语句中引用)。如果您使用,则尤其会发生这种情况docker build --pull。您需要仔细查看构建器的第一的层,其中包含基础映像的 SHA-256 校验和。如果它不断变化,就没有真正的“修复”。您的映像应该需要重建,以包含基础映像的最新安全修复。但是,如果基础映像重建常常(例如,每天多次),您可能希望停止使用该--pull标志,而是采用仅运行docker pull <base image>(或删除基础图像)的更新频率较低,例如每天一次。
  • 每当文件发生变化而您没有注意到(您尚未将其包含在您的文件中)时,层 forCOPY或语句都会“意外”重建。这可能是文件夹,或在构建/测试期间创建的文件(例如单元测试报告文件或日志文件)。这通常发生在运行 时,因为那时您的整个项目目录都会从构建上下文复制到构建容器中,这增加了您错过通过 排除一些多余文件(无论如何不属于容器)的机会。为了轻松解决这个问题,我开发了一个小型 CLI 工具,名为ADD.dockerignore.gitCOPY . ..dockerignore目录校验和。它以递归方式计算目录内容的校验和,并打印校验和直到您可以指定的深度。

相关内容