【问题标题】:How to list all files from the build context that affect the contents of the image?如何从构建上下文中列出影响图像内容的所有文件?
【发布时间】:2021-04-28 19:29:24
【问题描述】:

是否可以列出从构建上下文复制到映像中的所有文件,或以任何其他方式影响映像的最终内容?

我需要这个来进行依赖跟踪;我正在为一个项目设计一个构建系统,该项目涉及在本地开发环境中构建多个图像并从中运行容器。我需要针对快速的代码构建调试周期进行优化,因此我需要能够尽可能避免调用docker build。了解构建上下文中最终影响映像的确切文件集将允许我将这些文件指定为调用docker build 的构建步骤的跟踪依赖项,并避免不必要的重建。

我不需要提前生成这个文件列表,虽然这是首选。如果没有工具可以预先生成它,但是有办法从构建的图像中获取它,那也可以;我使用的构建工具能够记录构建后步骤发现的动态依赖关系。

敏锐地意识到的事情,并且我仍然做出明智的决定认为追求这条道路是值得的:

  • 我知道如此跟踪的依赖项数量可能非常庞大。我相信构建工具可以处理它。
  • 我知道除了构建上下文中的文件之外,Docker 映像还有其他类型的依赖项。这也可以通过跟踪docker build 之外的那些依赖关系来解决。与构建上下文中的文件不同,这些依赖项的数量要少得多(即 Dockerfile 的 RUN 命令显式从 Internet 获取的文件),或者已经解决了获取此类依赖项的详尽列表的问题(例如,获得的依赖项使用像apt-get这样的包管理器是单独建模的,安装RUNs是从模型生成到Dockerfile中的)。

【问题讨论】:

  • 整个目的是获取可以用来决定是否可以跳过发出docker build的信息。如果获取此信息需要发出docker build,那就达不到目的了。

标签: docker dockerfile


【解决方案1】:

我认为即使有可能,您正在寻找的内容也不会有用。先前构建的映像中所有文件的列表不会考虑新文件,并且很难区分影响构建的新文件和将被忽略的新文件。

您可以解析 Dockerfile,提取每个 COPY 和 ADD 命令,通过散列过程运行当前文件以识别它们是否从图像历史记录中的散列更改(您需要匹配 docker 的散列算法,其中包括文件所有权和权限等详细信息),然后当该哈希不匹配时,您将知道构建需要再次运行。您可以考虑创建自定义 buildkit 语法解析器,或重用低级 buildkit 代码来构建您自己的上下文处理器。

但在您花太多时间尝试实现上述代码之前,请意识到它已经存在,如docker build。我不会试图避免运行构建,而是专注于让构建利用构建缓存,以便新构建跳过所有未更改的步骤,可能会生成完全相同的图像 ID。

【讨论】:

  • 是的,我意识到docker build 已经存在。即使在 100% 缓存构建的情况下,它做的工作要多得多,而且比确定是否有 100 多个本地文件更改要慢得多。哎呀,我当前基于 git 标记整个构建上下文的解决方案比在不变的上下文上重新运行 docker build 快大约 5 倍,即使我的解决方案在整个 monorepo 上运行 git diff。所以请不要告诉我我正在重新发明轮子。 Docker 的“轮子”是方形的,我已经发明了一个大致为八角形的(一个巨大的改进),我想要一个真正的圆形。
  • 当然,我的 gitstamping 解决方案无法处理 .dockerignore,因此如果 dockerignored 文件发生更改,它确实会触发虚假重建。这就是为什么我正在寻找一个真正的解决方案。
  • @SzczepanHołyszewski 只是为了验证您正在使用 buildkit 而没有将结果推送到外部注册表?
  • 是的,我正在使用 buildkit。一些构建目标涉及将图像推送到外部注册表,有些则没有。在任何一种情况下,跳过docker build 都会产生可衡量的好处。在代码-构建-调试周期中,它通常决定了留在流程中还是退出流程。
  • @SzczepanHołyszewski 听起来你已经把自己缩小到了第二段。确保在复制散列代码以考虑 dockerignore 文件时。我可能会查看 Dockerfile 解析器的 buildkit 存储库来提取副本并添加命令。一旦你有了所有这些,你就可以将哈希值与之前的图像进行比较。
【解决方案2】:

除非您明确说明,否则不会将任何内容复制到图像中。所以,检查你的 Dockerfile 中的 COPY 语句,你就会知道构建上下文中的哪些文件被添加到了镜像中。

请注意,如果您有 COPY . .,那么您可能在构建上下文中有一个 .dockerignore 文件,其中包含您不想复制的文件。

【讨论】:

  • 这正是问题所在:获取关于 Docker 实际用于构建映像的确切构建上下文文件集的真相,并在不解析 Dockerfile 和重新实现 docker 的树复制逻辑的情况下实现这一点, .dockerignore 逻辑,可能还有更多。
猜你喜欢
  • 2020-03-12
  • 2020-04-27
  • 1970-01-01
  • 2019-09-25
  • 2017-01-18
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多