我正在深入研究Docker buildx的缓存,试图调试一个问题。我试图弄清楚如何,确切地说,buildx检查一个层是否在本地缓存中可用。虽然我已经搜索了相当广泛,但我似乎找不到任何关于这方面的文档。
查看本地缓存文件本身,我看到了一堆带有散列名称的文件。我的假设是它的工作方式如下(假设使用type=local,mode=max
):
- 对于Dockerfile中的每一行,它使用一些参数组合来计算SHA哈希值。
- 它在
--cache-from
目录中检查是否存在以该哈希作为名称的文件 - 如果它存在,它使用该文件作为层,不重新构建任何东西(并将该文件复制到
--cache-to
目录)。 - 如果不存在,则构建该层并将其保存为文件,以该散列作为名称保存在
--cache-to
目录中。 - 这将导致Dockerfile中每行有一个输出缓存。
我的问题是:
- 我对这个过程的理解是否正确?我是否遗漏了什么关键元素?
- 对于上面的步骤(1),"参数"是什么?它用来计算哈希值的?我认为这是行本身的字符串值,加上由行复制的任何文件的值(例如
ADD
),但它是否使用其他任何东西?例如,它复制的任何文件的最后修改时间戳?
- 我对这个过程的理解是否正确?我是否遗漏了什么关键元素?
我的理解大致是这样的。我需要亲自检查代码以了解细节。
- 对于上面的步骤(1),"参数"是什么?它用来计算哈希值的?我认为这是行本身的字符串值,加上由行复制的任何文件的值(例如ADD),但它是否使用其他任何东西?例如,它复制的任何文件的最后修改时间戳?
一般来说,缓存Dockerfile步骤使用以下方法(这早于buildkit):
- 对于ADD/COPY步骤,源文件的散列。该散列包括文件所有权和权限。快速测试表明修改时间戳不包括在其中(在我触摸正在复制的文件后仍然使用缓存)。
- 对于RUN步骤,包括任何ENV或ARG键/值对,因为它们会修改环境以及正在运行的命令的文本。Docker没有从外部资源中提取命令的概念,也不知道哪些环境变量的变化会影响任何特定的命令。
- 对于所有步骤,缓存要求前一步的结果加上当前步骤的匹配(新的
COPY --link
可能是一个例外)。因此,如果您将新文件复制到映像中,那么该构建阶段的所有剩余步骤都不会在缓存中找到,docker无法一般地知道特定文件不会影响某些RUN步骤。