跳转至

Buildx

Buildx 是基于 BuildKit 的 Docker 扩展插件项目。Buildx 默认使用 BuildKit 引擎进行构建,本质上调用了 Buildkit 的 API,构建是在 Buildkit 的环境中进行的。

Buildx 是一个 Docker CLI 插件,它扩展了 docker build 命令的镜像构建功能,完整的支持 Moby BuildKit builder 工具包提供的特性。也提供了与 docker build 相似的操作体验,并提供了许多新构建特性,比如多架构镜像构建,以及并发构建。

相关的两个项目: - https://github.com/docker/buildx - https://github.com/moby/buildkit

docker buildx 主要特点: - 和 docker build 相似的操作体验 - 使用 docker-container 驱动可以支持完整的 BuildKit 功能 - 支持多构建器 builder 实例 - 支持多节构建跨平台的镜像 - 支持 Compose - 支持高级构建特性 (bake) - 支持容器内驱动,可以同时支持 Docker 和 Kubernetes

此外,Buildx 还支持常规 Docker 构建所没有的新特性,如构建清单列表 (manifest lists)、分布式缓存构建和将构建结果导出到OCI 镜像 tarball。

使用限制

  • Docker 版本限制。使用 buildx 作为 docker CLI 插件需要使用 Docker 19.03 或更新版本。旧版本的 Docker 可以单独安装调用二进制文件作为插件,可以支持部分功能。对于 Docker 版本大于 19.03 的版本,可以直接调用 buildx 二进制来访问 Docker buildx 子命令。
  • Linux 内核版本限制。要求 Linux kernel >= 4.8,因为自该 Linux 内核版本 binfmt_misc 才支持 fix-binary (F) flag。fix_binary 标志允许内核在容器或 chroot 内使用 binfmt_misc 注册的二进制格式处理程序,即使该处理程序二进制文件不是该容器或 chroot 内可见的文件系统的一部分。即可以支持编译打包不同架构平台的镜像。

[!TIP|style:flat] 是否支持多架构,取决于 Buildkit 的环境。 如果内核支持,Buildkit 可以直接支持多架构构建。 如果内核不支持,也可以通过 builder 关联不同架构的机器来进行构建。 如果上面两种方式都无法提供,可以在 Dockerfile 中使用交叉编译构建不同的二进制并打包镜像。

驱动

Buildx 具有灵活的特性,支持配置驱动的方式来运行在不同的场景,目前支持三种驱动方式,以后会计划支持更多的驱动。

  • 其一,支持 docker 驱动,将 BuildKit 库绑定到 Docker Daemon 守护进程中。直接使用 dockerd 服务的构建能力。
  • 其二,支持 docker-container 驱动,会自动在 Docker 容器中启动 BuildKit。
  • 其三,支持 kubernetes 驱动,它会自动启动带有定义的 BuildKit 容器镜像的 pod,以构建镜像。

用户即使选择的驱动不同,在使用 buildx 时的方式也基本一样。但有些特性目前 docker 驱动还不支持,因为绑定到 docker daemon 守护进程方式与 BuildKit 库目前使用了不同的存储组件。同时,所有使用 docker 驱动构建的镜像默认会自动添加到 docker images 视图中;而使用其他驱动时,需要使用 --output 选择输出镜像的方法。

builder 构建器实例

builder 构建器是一个或一组后端提供镜像构建的服务器实例(docker host)。默认情况下 buildx 最初会使用 docker 驱动,提供一个非常类似于原生 docker 构建的用户体验。注意,必须使用本地共享守护进程来构建应用程序。

Buildx 可以创建独立的 builder 实例。这可以用于给 CI 构建提供一个不影响系统共享 docker daemon 守护进程状态的环境,或者用于隔离不同项目的构建。您可以使用一组远程节点来创建新实例,形成构建集群,并在多个 builder 之间快速切换。

你可以使用 docker buildx create 命令创建新的 builder 实例。这将基于当前配置创建一个具有单个节点的 builder 构建器实例。

要使用远程节点,您可以在创建新的构建器时指定 DOCKER_HOST 或远程上下文名称。创建一个新实例后,你可以使用 docker buildx inspectdocker buildx stopdocker buildx rm 命令来管理它的生命周期。要列出所有可用的构建器,请使用 docker buildx ls。创建新构建器后,还可以向其添加新节点。

要在不同的构建器之间切换,使用 docker buildx use <name>。运行此命令后,构建命令将自动使用此构建器。

Docker 还有一个 docker context 命令,可以通过名称来访问远程 Docker API 的 endpoits 实例列表。Buildx 集成了 docker 上下文,这样所有的上下文都会自动获得一个默认的构建器实例。在创建新的构建器实例或向其添加节点时,还可以将上下文名称作为设置目标。

构建多架构镜像

[!TIP|style:flat] 多架构镜像(multiple platform image)是指一个镜像 TAG 可以同时提供运行在不同 CPU、操作系统上的镜像清单列表(manifest list)。

BuildKit 被设计成可以很好地支持多个平台进行镜像构建,而不仅仅是针对调用构建的用户当前运行的体系结构和操作系统。

当您调用构建时,可以设置 --platform 标志来指定构建输出的目标平台(例如,linux/amd64、linux/arm64 或 darwin/amd64)。

如果当前构建器实例由 docker-container 驱动 或 kubernetes 驱动程序支持时,您可以同时指定多个平台。在本例中,它构建一个清单列表(manifest list),其中包含所有指定体系结构的镜像。当你在 docker rundocker service 中使用这个镜像时,docker 会根据节点的平台选择正确的镜像。

你可以使用 Buildx 和 Dockerfiles 支持的三种不同策略来构建多平台映像:

  • 在内核中使用 QEMU 模拟支持
  • 使用相同的构建器实例在多个原生节点上构建
  • 使用 Dockerfile 中的一个阶段交叉编译到不同的架构

如果您的节点已经支持 QEMU,那么 QEMU 是最简单的启动方法(例如。如果你正在使用 Docker 桌面)。它不需要修改 Dockerfile,而且 BuildKit 会自动检测可用的二级架构。当 BuildKit 需要为不同的体系构建运行二进制文件时,它会通过在 binfmt_misc 处理程序中注册的二进制文件自动加载它。

为了在主机操作系统上注册到 binfmt_misc 的 QEMU 二进制文件透明地在容器中工作,它们必须使用fix_binary标志进行注册。这需要一个内核 kernel >= 4.8binfmt-support >= 2.1.7。您可以通过检查 F 是否在 /proc/sys/fs/binfmt_misc/qemu-* 中的标志中来检查是否正确注册。虽然 Docker Desktop 为其他平台预先配置了 binfmt_misc 支持,但可能依旧需要使用 tonistiigi/binfmt 镜像来安装。

$ docker run --privileged --rm tonistiigi/binfmt --install all
Unable to find image 'tonistiigi/binfmt:latest' locally
latest: Pulling from tonistiigi/binfmt
2b4d0e08bd75: Pull complete
c331be51c382: Pull complete
Digest: sha256:5bf63a53ad6222538112b5ced0f1afb8509132773ea6dd3991a197464962854e
Status: Downloaded newer image for tonistiigi/binfmt:latest
installing: arm64 OK
installing: s390x OK
installing: riscv64 OK
installing: arm OK
installing: ppc64le OK
installing: mips64le OK
installing: mips64 OK
{
  "supported": [
    "linux/amd64",
    "linux/ppc64le",
    "linux/s390x",
    "linux/386",
    "linux/arm/v7",
    "linux/arm/v6"
  ],
  "emulators": [
    "qemu-aarch64",
    "qemu-arm",
    "qemu-mips64",
    "qemu-mips64el",
    "qemu-ppc64le",
    "qemu-riscv64",
    "qemu-s390x"
  ]
}

查看构建器信息

# docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS  PLATFORMS
default * docker
  default default         running linux/amd64, linux/386, linux/riscv64, linux/arm/v7, linux/arm/v6, linux/s390x, linux/ppc64le, linux/arm64

使用多个原生节点可以支持 QEMU 无法处理的复杂情况,并且通常具有更好的性能。您可以使用 --append 标志向构建器实例添加额外的节点。

假设在 docker context ls 中存在 node-amd64node-arm64 上下文;

$ docker buildx create --use --name mybuild node-amd64
mybuild
$ docker buildx create --append --name mybuild node-arm64
$ docker buildx build --platform linux/amd64,linux/arm64 .

最后,根据您的项目,您使用的语言可能对交叉编译有很好的支持。在这种情况下,Dockerfiles 中的多阶段构建可以有效地用于为使用 --platform 指定的平台构建二进制文件,使用构建节点的本地架构。像 BUILDPLATFORM 和 TARGETPLATFORM 这样的构建参数列表在你的 Dockerfile 中自动可用,并且可以被作为构建的一部分运行的进程所利用。

FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log
FROM alpine
COPY --from=build /log /log

对于更高级的用例,您也可以使用 tonistiigi/xx Dockerfile 交叉编译助手。

Dockerfile 支持如下架构相关的变量

  • TARGETPLATFORM 构建镜像的目标平台,例如 linux/amd64, linux/arm/v7, windows/amd64。
  • TARGETOS TARGETPLATFORM 的 OS 类型,例如 linux, windows
  • TARGETARCH TARGETPLATFORM 的架构类型,例如 amd64, arm
  • TARGETVARIANT TARGETPLATFORM 的变种,该变量可能为空,例如 v7
  • BUILDPLATFORM 构建镜像主机平台,例如 linux/amd64
  • BUILDOS BUILDPLATFORM 的 OS 类型,例如 linux
  • BUILDARCH BUILDPLATFORM 的架构类型,例如 amd64
  • BUILDVARIANT BUILDPLATFORM 的变种,该变量可能为空,例如 v7

高级构建选项(bake)

Buildx 还旨在提供对高级构建概念的支持,而不仅仅是调用单个构建命令。我们希望支持同时构建应用程序中的所有映像,并让用户定义项目特定的可重用构建流,然后任何人都可以轻松调用这些构建流。

BuildKit 可以有效地处理多个并发构建请求和重复数据删除工作。构建命令可以与通用的命令运行程序(例如 make )结合使用。然而,这些工具通常是按顺序调用构建的,因此不能充分利用 BuildKit 并行化的潜力,也不能为用户组合 BuildKit 的输出。对于这个用例,我们添加了一个叫docker buildx bake 的命令。

bake 命令支持从 compose 文件构建映像,类似于 docker-compose 构建,但允许将所有服务作为单个请求的一部分并发构建。

它还支持从 HCL/JSON 文件中定制构建规则,从而实现更好的代码重用和不同的目标组。bake 的设计处于非常早期的阶段,我们正在寻找来自用户的反馈。

参考

Docker与Buildx

概述

Buildx是Docker生态中的一个强大工具,专为现代容器镜像构建需求设计。它基于BuildKit构建引擎,提供了比传统Docker构建工具更高效、更灵活的功能。Buildx不仅支持多架构镜像构建,还优化了构建缓存、并行构建和多阶段构建等特性,极大地提升了开发者的生产力。

核心功能

1. 多架构镜像构建

Buildx原生支持多架构镜像构建,允许开发者在单一构建命令中生成适用于不同CPU架构(如ARM、x86等)的镜像。这一功能特别适用于跨平台应用的开发和部署。

2. 跨平台构建支持

通过Buildx,开发者可以在一个平台上构建适用于其他平台的镜像。例如,在x86架构的机器上构建ARM架构的镜像,无需额外的硬件支持。

3. 构建缓存优化

Buildx利用BuildKit的先进缓存机制,显著减少了重复构建的时间。通过智能缓存管理,Buildx能够识别未更改的构建步骤,从而跳过这些步骤,提高构建效率。

4. 并行构建

Buildx支持并行构建,允许多个构建步骤同时进行,进一步缩短了构建时间。这对于大型项目或需要频繁构建的场景尤为重要。

5. 多阶段构建优化

Buildx优化了多阶段构建流程,使得开发者能够更高效地管理和利用中间构建阶段,减少最终镜像的大小和复杂性。

6. 灵活的构建输出格式

Buildx支持多种构建输出格式,包括OCI镜像和Docker镜像。开发者可以根据需求选择合适的输出格式,满足不同的部署和分发需求。

使用场景

1. 跨平台应用开发

对于需要在多种硬件架构上运行的应用,Buildx的多架构镜像构建功能可以显著简化开发和部署流程。

2. 持续集成与持续部署(CI/CD)

在CI/CD流水线中,Buildx的高效构建和缓存机制可以大幅缩短构建时间,提高整体流程的效率。

3. 微服务架构

在微服务架构中,Buildx的多阶段构建优化和并行构建功能可以帮助开发者更高效地管理和构建多个服务镜像。

与其他章节的区别

  • 与“Dockerfile”章节的区别:本文重点在于Buildx工具的使用和优化,而非Dockerfile语法或构建指令的详细解析。
  • 与“镜像管理”章节的区别:本文专注于Buildx在多架构镜像构建中的具体应用,而非镜像的存储、推送、拉取等管理操作。
  • 与“最佳实践”章节的区别:本文更侧重于Buildx的技术实现和功能特性,而非通用的Docker使用最佳实践。
  • 与“原理解析”章节的区别:本文聚焦于Buildx的实际应用场景和功能优势,而非底层技术原理的深度剖析。

示例

以下是一个使用Buildx构建多架构镜像的示例:

# 创建一个新的构建器实例
docker buildx create --use

# 构建多架构镜像
docker buildx build --platform linux/amd64,linux/arm64 -t myimage:latest .

结论

Buildx作为Docker生态中的重要工具,为开发者提供了强大的多架构镜像构建和跨平台支持能力。通过其高效的构建缓存、并行构建和多阶段构建优化功能,Buildx显著提升了镜像构建的效率和灵活性。无论是跨平台应用开发、CI/CD流水线还是微服务架构,Buildx都能为开发者带来显著的便利和优势。

通过本文,读者将全面了解Buildx在Docker生态中的独特价值,掌握如何利用Buildx提升镜像构建效率并支持跨平台应用开发。