Docker buildx 层缓存哈希是如何计算的?

How are Docker buildx layer cache hashes calculated?

我正在深入研究 Docker buildx 的缓存以尝试调试 an issue。我试图弄清楚 buildx 究竟是如何检查本地缓存中是否有图层可用的。尽管我进行了相当广泛的搜索,但我似乎找不到任何关于此的文档。

查看本地缓存文件本身,我看到一堆具有哈希名称的文件。我的假设是它的工作原理如下(假设使用 type=local,mode=max):

  1. 对于 Docker 文件中的每一行,它使用一些参数组合来计算 SHA 哈希。
  2. 它检查 --cache-from 目录以查看是否存在以该哈希作为名称的文件
  3. 如果它确实存在,它将使用该文件作为图层并且不会重新构建任何东西(并将该文件复制到 --cache-to 目录。
  4. 如果 存在,它会构建层并将其保存为一个文件,以该散列作为名称,在 --cache-to 目录中。
  5. 这会导致 Docker 文件中的每一行都有 1 个文件的输出缓存。

所以我的问题是:

  1. 我对这个过程的理解是否正确?我是否遗漏了任何关键要素?
  2. 对于上面的第(1)步,它用来计算散列的“参数”是什么?我认为它是该行本身的字符串值,加上该行复制的任何文件的值(例如 ADD),但它是否使用其他任何东西?例如它复制的任何文件的最后修改时间戳?
  1. Is my understanding of this process correct? Am I missing any key elements?

我的理解大致是这样的。我需要自己检查代码才能了解具体情况。

  1. For step (1) above, what are the "parameters" that it uses to calculate the hash? I would think it's the string value of the line itself, plus the value of any files that are copied by the line (e.g. ADD), but does it use anything else? e.g. the last-modified timestamp of any files that it copies?

通常,Docker 文件步骤的缓存使用以下内容(这早于 buildkit):

  • 对于 ADD/COPY 步骤,源文件的散列。该散列包括文件所有权和权限。快速测试表明修改时间戳不包含在其中(在我触摸正在复制的文件后缓存仍在使用)。
  • 对于 运行 步骤,任何 ENV 或 ARG key/value 对都包括在内,因为它们修改环境,命令文本为 运行。 Docker 没有从外部资源拉取命令的概念,也不知道什么环境变量变化会影响任何特定命令。
  • 对于所有步骤,缓存要求上一步的结果加上当前步骤的结果匹配(新的COPY --link可能是例外)。因此,如果您将一个新文件复制到映像中,该构建阶段的所有剩余步骤将不再在缓存中找到,docker 无法一般地知道特定文件不会影响某些 运行 步骤。