几周前,用于构建 Dockerfiles 的 Docker 的 BuildKit 工具现在支持 heredoc 语法!有了这些新的改进,我们可以做各种以前困难的事情,比如多行运行,而不需要每行末尾那些讨厌的反斜杠,或者创建小的内联配置文件。在这篇文章中,我将介绍这些文档的基础知识,更重要的是您可以使用它们做什么,以及如何开始使用它们! 🎉 BuildKit 是一个工具包,用于以高效、富有表现力和可重复的方式将源代码转换为构建工件。从本质上讲,它是 docker 镜像的下一代构建器,与主要 docker 运行时的其余部分巧妙地分开;您可以使用它来构建 docker 镜像,或用于其他 OCI 运行时的镜像。它带有许多超出 basicbuilder 支持的有用(且漂亮)的功能,包括更整洁的构建日志输出、更快且更高效的缓存构建、并发构建,以及非常灵活的架构以允许轻松扩展(我绝对不是公正对待)。您很可能已经在使用它,或者您可能想使用它!您可以在执行 docker build 时通过设置环境变量 DOCKER_BUILDKIT=1 在本地启用它,或者切换到使用 new(ish) docker buildx 命令。在技术层面上,buildkit 允许在多个不同的“构建器”之间轻松切换,这些构建器可以是本地的或远程的、在 dockerdaemon 本身、在 docker 容器中甚至在 Kubernetes pod 中。构建器本身分为两个主要部分,前端和后端:前端生成中间低级构建器 (LLB) 代码,然后由后端将其构建为图像。
buildkit 如此出色的部分原因在于它的灵活性——这些组件彼此完全分离,因此您可以在任何图像中使用任何前端。例如,您可以使用默认的 Dockerfile 前端,或编译您自己的独立构建包,甚至开发您自己的替代文件格式,如 Mockerfile。要开始使用heredocs,首先确保你使用buildkit 进行设置。切换到buildkit 会给你的build 设置提供大量开箱即用的改进,并且应该与旧的构建器完全兼容(并且你总是可以如果您不喜欢它,请切换回来)。正确设置 buildkit 后,您可以创建一个新的 Dockerfile:在此文件的顶部,我们需要包含一个 #syntax= 指令。该指令通知解析器使用特定的前端 - 在这种情况下,位于 docker/dockerfile:1.3-labson Docker Hub 的前端。有了这一行(必须是第一行),buildkit 将找到并下载正确的镜像,然后使用它来构建镜像。有了这些,我们可以使用一个 heredoc,在同一个 RUN 中执行两个命令!现在heredocs 正在起作用,您可能想知道-为什么要大惊小怪?好吧,到目前为止,Dockerfiles 中还缺少此功能。假设您想要构建一个需要大量命令来设置的映像。例如,Dockerfiles 中一个相当常见的模式涉及想要更新系统,然后安装一些额外的依赖项,即一次 apt 更新、升级和安装。
但是,遗憾的是,像太多直观的解决方案一样,这并不能完全满足我们的需求。它当然有效 - 但我们为每次 RUN 创建一个新层,使我们的图像比它需要的大得多(并且构建需要更长的时间)。这就是今天大多数 Dockerfile 所做的,从官方的 docker 镜像到我为自己编写的凌乱的镜像。它工作正常,图像小而快速构建......但它看起来确实有点难看。如果你不小心忘记了换行符\,那么你会得到一个语法错误!我们使用 <<EOF 来引入 heredoc(就像在 sh/bash/zsh/yourshell 中选择的一样),并在最后使用 EOF 来关闭它。在这两者之间,我们将所有命令作为脚本的内容由 shell 运行!到目前为止,我们已经看到了一些基本的语法。然而,新的 heredoc 支持不仅仅允许简单的例子,还有很多其他有趣的事情你可以做。但是假设您的设置脚本变得越来越复杂,并且您想使用另一种语言 - 例如 Python。好吧,没问题,您可以将heredocs连接到其他程序!事实上,你可以在heredocs中使用你喜欢的复杂命令,将上面的简化为:如果感觉有点繁琐或复杂,你也可以总是使用shebang:
有很多不同的方法可以将 heredocs 连接到 RUN,希望将来会有更多的方法和改进! Dockerfiles 中的 Heredocs 也让我们处理内联文件!假设您正在构建一个 nginx 站点,并且想要创建一个自定义索引页面:然后在单独的文件 index.html 中放置您的内容。但是如果你的索引页面真的很简单,把所有东西都分开会让人感到沮丧:如果你愿意,heredocs 让你把所有东西都放在同一个地方!希望我已经成功说服你尽可能尝试使用heredocs!目前,它们仍然只在登台前端可用,但它们应该很快就会发布 - 所以一定要采取看看并提供您的反馈!