使用Bake构建Compose项目
本指南探讨了如何使用Bake为具有多个服务的Docker Compose项目构建镜像。
Docker Buildx Bake 是一个构建编排工具,它允许您以声明式的方式配置构建,就像 Docker Compose 用于定义运行时堆栈一样。对于使用 Docker Compose 启动本地开发服务的项目,Bake 提供了一种无缝扩展项目的方式,使其具备生产就绪的构建配置。
先决条件
本指南假设您熟悉
方向
本指南将使用 dvdksn/example-voting-app 仓库作为使用Docker Compose的单仓库示例,可以通过Bake进行扩展。
$ git clone https://github.com/dvdksn/example-voting-app.git
$ cd example-voting-app
此仓库使用 Docker Compose 来定义运行应用程序的运行时配置,位于 compose.yaml 文件中。此应用程序由以下服务组成:
| Service | Description |
|---|---|
vote | A front-end web app in Python which lets you vote between two options. |
result | A Node.js web app which shows the results of the voting in real time. |
worker | A .NET worker which consumes votes and stores them in the database. |
db | A Postgres database backed by a Docker volume. |
redis | A Redis instance which collects new votes. |
seed | A utility container that seeds the database with mock data. |
vote、result 和 worker 服务是从此仓库中的代码构建的,而 db 和 redis 使用了 Docker Hub 上已有的 Postgres 和 Redis 镜像。seed 服务是一个实用工具,用于调用前端服务的请求以填充数据库,用于测试目的。
使用 Compose 构建
当你启动一个Docker Compose项目时,任何定义了build属性的服务都会在服务启动之前自动构建。以下是示例仓库中vote服务的构建配置:
services:
vote:
build:
context: ./vote # Build context
target: dev # Dockerfile stagevote、result 和 worker 服务都指定了构建配置。运行 docker compose up 将触发这些服务的构建。
你知道吗,你也可以使用Compose来构建服务镜像?
docker compose build 命令允许你使用Compose文件中指定的构建配置来调用构建。例如,要使用此配置构建vote服务,请运行:
$ docker compose build vote
省略服务名称以一次性构建所有服务:
$ docker compose build
当您只需要构建镜像而不需要运行服务时,docker compose build 命令非常有用。
Compose 文件格式支持许多属性来定义您的构建配置。例如,要指定镜像的标签名称,请在服务上设置 image 属性。
services:
vote:
image: username/vote
build:
context: ./vote
target: dev
#...
result:
image: username/result
build:
context: ./result
#...
worker:
image: username/worker
build:
context: ./worker
#...运行 docker compose build 会创建三个服务镜像,这些镜像具有完全限定的镜像名称,您可以将其推送到 Docker Hub。
build 属性支持
多种选项
用于配置构建。然而,生产级镜像的构建通常与本地开发中使用的镜像不同。为了避免在 Compose 文件中混杂可能不适合本地构建的配置,考虑通过使用 Bake 来构建发布镜像,从而将生产构建与本地构建分开。这种方法分离了关注点:使用 Compose 进行本地开发,使用 Bake 进行生产就绪的构建,同时仍然重用服务定义和基本构建配置。
使用Bake构建
与Compose类似,Bake从配置文件中解析项目的构建定义。Bake支持HashiCorp配置语言(HCL)、JSON和Docker Compose YAML格式。当您使用多个文件进行Bake时,它将找到并合并所有适用的配置文件为一个统一的构建配置。在Compose文件中定义的构建选项会被Bake文件中指定的选项扩展,或在某些情况下被覆盖。
以下部分探讨了如何使用Bake扩展在Compose文件中定义的生产构建选项。
查看构建配置
Bake 自动从您的服务的 build 属性创建构建配置。使用 --print 标志让 Bake 查看给定 Compose 文件的构建配置。此标志评估构建配置并以 JSON 格式输出构建定义。
$ docker buildx bake --print
JSON格式的输出显示了将要执行的组,以及该组的所有目标。一个组是构建的集合,而一个目标代表一个单独的构建。
{
"group": {
"default": {
"targets": [
"vote",
"result",
"worker",
"seed"
]
}
},
"target": {
"result": {
"context": "result",
"dockerfile": "Dockerfile",
},
"seed": {
"context": "seed-data",
"dockerfile": "Dockerfile",
},
"vote": {
"context": "vote",
"dockerfile": "Dockerfile",
"target": "dev",
},
"worker": {
"context": "worker",
"dockerfile": "Dockerfile",
}
}
}如你所见,Bake 创建了一个 default 组,其中包含四个目标:
seedvoteresultworker
这个组是从你的Compose文件自动创建的;它包括所有包含构建配置的服务。要使用Bake构建这组服务,请运行:
$ docker buildx bake
自定义构建组
首先重新定义Bake执行的默认构建组。当前的默认组包括一个seed目标——一个仅用于用模拟数据填充数据库的Compose服务。由于此目标不生成生产镜像,因此不需要包含在构建组中。
要自定义Bake使用的构建配置,请在仓库的根目录下创建一个新文件,与您的compose.yaml文件并列,命名为docker-bake.hcl。
$ touch docker-bake.hcl
打开Bake文件并添加以下配置:
group "default" {
targets = ["vote", "result", "worker"]
}保存文件并再次打印您的Bake定义。
$ docker buildx bake --print
JSON输出显示default组仅包含您关心的目标。
{
"group": {
"default": {
"targets": ["vote", "result", "worker"]
}
},
"target": {
"result": {
"context": "result",
"dockerfile": "Dockerfile",
"tags": ["username/result"]
},
"vote": {
"context": "vote",
"dockerfile": "Dockerfile",
"tags": ["username/vote"],
"target": "dev"
},
"worker": {
"context": "worker",
"dockerfile": "Dockerfile",
"tags": ["username/worker"]
}
}
}在这里,每个目标(上下文、标签等)的构建配置都是从compose.yaml文件中获取的。组由docker-bake.hcl文件定义。
自定义目标
Compose 文件目前将 dev 阶段定义为 vote 服务的构建目标。这对于您在本地开发中运行的镜像是合适的,因为 dev 阶段包含了额外的开发依赖项和配置。然而,对于生产镜像,您将希望以 final 镜像为目标。
要修改vote服务使用的目标阶段,请将以下配置添加到Bake文件中:
target "vote" {
target = "final"
}当您使用Bake运行构建时,这将覆盖Compose文件中指定的target属性,并使用不同的值。Compose文件中的其他构建选项(如tag、context)保持不变。您可以通过使用docker buildx bake --print vote检查vote目标的构建配置来验证:
{
"group": {
"default": {
"targets": ["vote"]
}
},
"target": {
"vote": {
"context": "vote",
"dockerfile": "Dockerfile",
"tags": ["username/vote"],
"target": "final"
}
}
}额外的构建功能
生产级构建通常具有与开发构建不同的特性。以下是一些您可能希望为生产镜像添加的内容示例。
- Multi-platform
- For local development, you only need to build images for your local platform, since those images are just going to run on your machine. But for images that are pushed to a registry, it's often a good idea to build for multiple platforms, arm64 and amd64 in particular.
- Attestations
- 证明 are manifests attached to the image that describe how the image was created and what components it contains. Attaching attestations to your images helps ensure that your images follow software supply chain best practices.
- Annotations
- 注释 provide descriptive metadata for images. Use annotations to record arbitrary information and attach it to your image, which helps consumers and tools understand the origin, contents, and how to use the image.
提示
为什么不直接在Compose文件中定义这些额外的构建选项呢?
Compose 文件格式中的
build属性并不支持所有的构建功能。此外,一些功能,如多平台构建,可能会显著增加构建服务所需的时间。对于本地开发,最好保持构建步骤简单快速,将复杂的功能留到发布构建时使用。
要将这些属性添加到您使用Bake构建的镜像中,请按如下方式更新Bake文件:
group "default" {
targets = ["vote", "result", "worker"]
}
target "_common" {
annotations = ["org.opencontainers.image.authors=username"]
platforms = ["linux/amd64", "linux/arm64"]
attest = [
"type=provenance,mode=max",
"type=sbom"
]
}
target "vote" {
inherits = ["_common"]
target = "final"
}
target "result" {
inherits = ["_common"]
}
target "worker" {
inherits = ["_common"]
}这定义了一个新的_common目标,该目标定义了可重用的构建配置,用于向您的镜像添加多平台支持、注释和证明。可重用的目标由构建目标继承。
通过这些更改,使用Bake构建项目会为linux/amd64和linux/arm64架构生成三组多平台镜像。每个镜像都带有作者注释,并且包含SBOM和来源证明记录。
结论
本指南中展示的模式为使用Docker Compose的项目管理生产就绪的Docker镜像提供了一种有用的方法。使用Bake可以让您访问Buildx和BuildKit的所有强大功能,并且有助于以合理的方式分离您的开发和构建配置。
进一步阅读
有关如何使用 Bake 的更多信息,请查看以下资源: