为什么COPY指令在我的Docker构建中导致缓存未命中

ima*_*son -1 haskell travis-ci docker haskell-stack

我的项目在docker文件中的复制指令似乎导致缓存未命中,即使自从上次将映像推送到docker hub以来,复制的文件均未更改。这将导致所有后续层丢失高速缓存,从而使构建花费的时间大大超过了应有的时间。我还注意到,属于每层的哈希似乎与docker build在本地计算机上时的哈希不同。这可能是因为Docker版本不匹配吗?这里发生了什么?我该如何诊断?

BMi*_*tch 6

检查使用构建的不同图像的层docker history --no-trunc $image。在复制步骤中,您将看到正在复制的文件的“ file:abc”哈希:

IMAGE                                                                     CREATED             CREATED BY                                                                                                        SIZE                COMMENT
sha256:202cb043f70a2565ea40629e891642e1e24be7b52e29116a6520736f47183904   9 minutes ago       /bin/sh -c #(nop) COPY file:d523f0d1cac93e44179baf9c36a7a4feff221b604224e26900075ddb02812448 in /test/test.txt    12B
Run Code Online (Sandbox Code Playgroud)

如果您要构建的两个映像之间的哈希值不同,则将使构建缓存无效并导致未命中。请记住,文件的元数据也会导致缓存未命中,尤其是文件权限。如果仍然有问题,请更新问题以包括docker history --no-trunc ...不同版本的输出。


esm*_*ail 5

如果您的文件内容确实没有更改,则权限差异可能会导致缓存失效。

对于 ADD 和 COPY 指令,将检查映像中文件的内容并计算每个文件的校验和。这些校验和中不考虑文件的上次修改时间和上次访问时间。在缓存查找期间,会将校验和与现有映像中的校验和进行比较。如果文件中发生任何更改,例如内容和元数据,则缓存将失效。

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

编辑

从 Docker 20.10 开始,如果您使用 BuildKit,则添加了一个--chmod参数(不幸的是,尚未在文档中)。因此,您可以确保图像中的权限一致,并避免与权限相关的缓存丢失,例如COPYADD

COPY --chmod=<4-byte octal mask> ...

  • 目前,这种情况在 GitLab CI 中发生,是因为一个 [bug](https://gitlab.com/gitlab-org/gitlab-runner/issues/1736) 导致使用 666 权限克隆源。 (2认同)