如何使用 Docker Buildx Bake 创建复杂的镜像构建管道

已发表: 2022-08-10

显示 Docker 徽标的图形

docker buildx命令组使用 BuildKit 来公开高级镜像构建功能。 烘焙构建是一种高级功能,可用于定义自动构建管道。 它们使您可以从单个构建操作中生成多个图像。

当您想要发布图像的不同变体或并行构建多个链接项目时,烘焙工作流程很有帮助。 在本文中,我们将介绍docker buildx bake的主要功能以及如何使用它们来简化复杂的构建。

入门

docker buildx bake命令执行多个构建“目标”,每个构建“目标”都会生成一个容器映像。 目标尽可能并行运行,以最大限度地提高性能。 目标也可以直接引用前任来创建顺序管道。

可以使用几种不同的机制定义构建目标,包括现有的 Docker Compose 文件。 Buildx 将自动构建文件中标识的所有图像。

当您在 JSON 或 HCL 文件中列出构建目标时,会公开更多高级功能。 这些支持变量、函数和值插值来自定义您的构建。

buildx bake命令按顺序查找以下文件:

  • docker-compose.yml
  • docker-compose.yaml
  • docker-bake.json
  • docker-bake.override.json
  • docker-bake.hcl
  • docker-bake.override.hcl

您可以使用-f命令标志指定不同的文件。

构建目标

构建目标封装了与您的构建相关的所有配置。 它们包括详细信息,例如

  • 要构建的 Dockerfile 的路径
  • 构建上下文路径,定义 Dockerfile 中可用的内容
  • 附加到输出图像的标签和标签
  • 为其生成图像的平台。

文档中提供了支持的配置字段的完整列表。 以前,您可能已经将这些设置作为命令行标志提供给docker buildx build (甚至是普通的 docker docker build ),迫使您每次都记住正确的值。 使用buildx bake ,您可以通过在受版本控制的烘焙文件中定义它们来可靠地使用相同的值。

这是定义单个构建目标docker-bake.hcl命令的简单示例:

 target "default" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] }

使用此烘焙文件运行docker buildx bake buildx bake 将从您的工作目录加载app/Dockerfile Dockerfile。 它可以访问app/srcshared-components/src目录作为构建上下文。 生成的图像将被分配两个标签。

运行docker buildx bake时会自动构建default目标。 您还可以定义可以按需构建的命名目标:

 target "app" { // ... }
 $ docker buildx bake app

使用多个目标

您可以通过在烘焙文件中将其定义为新目标来同时构建另一个图像:

 group "default" { targets = ["app", "api"] } target "app" { dockerfile = "app/Dockerfile" contexts = { app = "app/src" shared = "shared-components/src" } tags = ["my-app:latest", "docker.io/my-org/my-app:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { src = "api/src" } tags = ["my-api:latest", "docker.io/my-org/my-api:latest"] }

这些图像可以同时构建,因为它们嵌套在一个组中。 每次运行docker buildx bake命令时, apiapp映像将并行构建,因为default组是自动选择的。 您可以使用与上述命名目标示例类似的命名组。

构建目标继承

构建目标可以相互继承以重用配置。 这可能有用的一种情况涉及需要为不同环境定制的图像。 您可能希望将额外的配置文件添加到旨在用于开发的图像变体中。 这是演示此模型docker-bake.hcl

 group "default" { targets = ["backend", "backend-dev"] } target "backend" { dockerfile = "backend/Dockerfile" contexts = { src = "api/src" config = "api/config" } tags = ["backend:latest"] } target "backend-dev" { inherits = ["backend"] contexts = { config = "api/config-dev" } tags = ["backend:dev"] }

backend-dev目标继承了backend目标的所有属性,但覆盖了config上下文并应用了不同的标签。

您可以通过运行带有--print标志的bake命令来预览合并的文件结构:

 $ docker buildx bake --print ... "backend-dev": { "context": ".", "contexts": { "config": "api/config-dev", "src": "api/src" }, "dockerfile": "backend/Dockerfile", "tags": [ "backend:dev" ] } ...

使用先前的目标作为基础图像

有时您可能希望构建目标使用由先前目标创建的映像作为其自己的基础。 这是多阶段构建的替代方案,当您的 Dockerfile 相互依赖但无法合并在一起时,可以使用它,这可能是因为它们存在于不同的项目中。

 group "default" { targets = ["org-base-image", "api"] } target "org-base-image" { dockerfile = "docker-base/Dockerfile" tags = ["org-base-image:latest"] } target "api" { dockerfile = "api/Dockerfile" contexts = { base = "target:org-base-image" } tags = ["api:latest"] }

该示例首先构建org-base-image目标。 这可能包含您组织的容器化工作负载常见的一些实用程序。 然后使用org-base-image目标的输出构建api目标,该目标可作为base构建上下文访问。 API Dockerfile 现在可以引用基础镜像中的内容:

 COPY --from=base /utilities/example /usr/bin/example-utility

这是一种强大的模式,可让您在镜像之间创建依赖链接,同时维护单独的 Dockerfile。

在构建时覆盖目标的属性

docker buildx bake命令允许您在运行构建时覆盖目标的属性:

 $ docker buildx bake --set api.dockerfile="api/Dockerfile-dev"

此示例更改api目标的 Dockerfile。 识别要更改的目标时支持*通配符。 *自己选择每个目标,而api*将修改所有以api开头的目标。

设置变量

HCL 文件可以定义您可以在构建目标中引用的变量。 使用variable块来设置它们:

 variable "TAG" { default = "latest" } group "default" { targets = ["app"] } target "app" { dockerfile = "src/Dockerfile" tags = ["my-app:${TAG}"] }

使用此配置运行docker buildx bake会将app目标标记为my-app:latest 。 您可以在执行命令之前通过设置环境变量来更改TAG变量的值:

 $ TAG=v1 docker buildx bake

您可以使用 HCL 语言的所有变量插值和比较功能来使您的构建目标可重用。 函数也可用于解析和转换您的值。

概括

Baked Buildx 构建允许您将映像构建配置封装为文件中定义的“目标”。 当您运行buildx bake时,所有引用目标的图像都是并行构建的。

目标可以相互继承并相互依赖。 您还可以使用变量和函数来创建高度复杂且可配置的构建管道。

docker buildx bake命令是一个高级操作,并非在每个工作流程中都需要。 当您创建没有跨项目依赖关系的简单图像时,您不需要使用它。 对于大多数将构建配置保存在docker-compose.yml文件中的用例来说,使用 docker docker compose build是一种更好的选择。 当您使用不同的变量、平台、构建上下文和配置覆盖同时构建多个图像时,应考虑切换到烘焙构建。