1. docker buildx
Buildx 是基于 BuildKit 的 Docker 扩展插件项目。Buildx 默认使用 BuildKit 引擎进行构建,本质上调用了 Buildkit 的 API,构建是在 Buildkit 的环境中进行的。
Buildx 是一个 Docker CLI 插件,它扩展了 docker build
命令的镜像构建功能,完整的支持 Moby BuildKit builder 工具包提供的特性。也提供了与 docker build
相似的操作体验,并提供了许多新构建特性,比如多架构镜像构建,以及并发构建。
相关的两个项目:
docker buildx
主要特点:
- 和
docker build
相似的操作体验 - 使用 docker-container 驱动可以支持完整的 BuildKit 功能
- 支持多构建器 builder 实例
- 支持多节构建跨平台的镜像
- 支持 Compose
- 支持高级构建特性 (bake)
- 支持容器内驱动,可以同时支持 Docker 和 Kubernetes
此外,Buildx 还支持常规 Docker 构建所没有的新特性,如构建清单列表 (manifest lists)、分布式缓存构建和将构建结果导出到OCI 镜像 tarball。
1.1. 使用限制
- 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 中使用交叉编译构建不同的二进制并打包镜像。
1.2. 驱动
Buildx 具有灵活的特性,支持配置驱动的方式来运行在不同的场景,目前支持三种驱动方式,以后会计划支持更多的驱动。
- 其一,支持
docker
驱动,将 BuildKit 库绑定到 Docker Daemon 守护进程中。直接使用 dockerd 服务的构建能力。 - 其二,支持
docker-container
驱动,会自动在 Docker 容器中启动 BuildKit。 - 其三,支持
kubernetes
驱动,它会自动启动带有定义的 BuildKit 容器镜像的 pod,以构建镜像。
用户即使选择的驱动不同,在使用 buildx 时的方式也基本一样。但有些特性目前 docker
驱动还不支持,因为绑定到 docker daemon 守护进程方式与 BuildKit 库目前使用了不同的存储组件。同时,所有使用 docker
驱动构建的镜像默认会自动添加到 docker images
视图中;而使用其他驱动时,需要使用 --output
选择输出镜像的方法。
1.3. builder 构建器实例
builder 构建器是一个或一组后端提供镜像构建的服务器实例(docker host)。默认情况下 buildx 最初会使用 docker
驱动,提供一个非常类似于原生 docker 构建的用户体验。注意,必须使用本地共享守护进程来构建应用程序。
Buildx 可以创建独立的 builder 实例。这可以用于给 CI 构建提供一个不影响系统共享 docker daemon 守护进程状态的环境,或者用于隔离不同项目的构建。您可以使用一组远程节点来创建新实例,形成构建集群,并在多个 builder 之间快速切换。
你可以使用 docker buildx create
命令创建新的 builder 实例。这将基于当前配置创建一个具有单个节点的 builder 构建器实例。
要使用远程节点,您可以在创建新的构建器时指定 DOCKER_HOST 或远程上下文名称。创建一个新实例后,你可以使用 docker buildx inspect
、docker buildx stop
和 docker buildx rm
命令来管理它的生命周期。要列出所有可用的构建器,请使用 docker buildx ls
。创建新构建器后,还可以向其添加新节点。
要在不同的构建器之间切换,使用 docker buildx use <name>
。运行此命令后,构建命令将自动使用此构建器。
Docker 还有一个 docker context
命令,可以通过名称来访问远程 Docker API 的 endpoits 实例列表。Buildx 集成了 docker 上下文,这样所有的上下文都会自动获得一个默认的构建器实例。在创建新的构建器实例或向其添加节点时,还可以将上下文名称作为设置目标。
1.4. 构建多架构镜像
[!TIP|style:flat] 多架构镜像(multiple platform image)是指一个镜像 TAG 可以同时提供运行在不同 CPU、操作系统上的镜像清单列表(manifest list)。
BuildKit 被设计成可以很好地支持多个平台进行镜像构建,而不仅仅是针对调用构建的用户当前运行的体系结构和操作系统。
当您调用构建时,可以设置 --platform
标志来指定构建输出的目标平台(例如,linux/amd64、linux/arm64 或 darwin/amd64)。
如果当前构建器实例由 docker-container
驱动 或 kubernetes
驱动程序支持时,您可以同时指定多个平台。在本例中,它构建一个清单列表(manifest list),其中包含所有指定体系结构的镜像。当你在 docker run
或 docker service
中使用这个镜像时,docker 会根据节点的平台选择正确的镜像。
你可以使用 Buildx 和 Dockerfiles 支持的三种不同策略来构建多平台映像:
- 在内核中使用 QEMU 模拟支持
- 使用相同的构建器实例在多个原生节点上构建
- 使用 Dockerfile 中的一个阶段交叉编译到不同的架构
如果您的节点已经支持 QEMU,那么 QEMU 是最简单的启动方法(例如。如果你正在使用 Docker 桌面)。它不需要修改 Dockerfile,而且 BuildKit 会自动检测可用的二级架构。当 BuildKit 需要为不同的体系构建运行二进制文件时,它会通过在 binfmt_misc 处理程序中注册的二进制文件自动加载它。
为了在主机操作系统上注册到 binfmt_misc 的 QEMU 二进制文件透明地在容器中工作,它们必须使用fix_binary标志进行注册。这需要一个内核 kernel >= 4.8
和 binfmt-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-amd64
和 node-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, windowsTARGETARCH
TARGETPLATFORM 的架构类型,例如 amd64, armTARGETVARIANT
TARGETPLATFORM 的变种,该变量可能为空,例如 v7BUILDPLATFORM
构建镜像主机平台,例如 linux/amd64BUILDOS
BUILDPLATFORM 的 OS 类型,例如 linuxBUILDARCH
BUILDPLATFORM 的架构类型,例如 amd64BUILDVARIANT
BUILDPLATFORM 的变种,该变量可能为空,例如 v7
1.5. 高级构建选项(bake)
Buildx 还旨在提供对高级构建概念的支持,而不仅仅是调用单个构建命令。我们希望支持同时构建应用程序中的所有映像,并让用户定义项目特定的可重用构建流,然后任何人都可以轻松调用这些构建流。
BuildKit 可以有效地处理多个并发构建请求和重复数据删除工作。构建命令可以与通用的命令运行程序(例如 make )结合使用。然而,这些工具通常是按顺序调用构建的,因此不能充分利用 BuildKit 并行化的潜力,也不能为用户组合 BuildKit 的输出。对于这个用例,我们添加了一个叫docker buildx bake
的命令。
bake 命令支持从 compose 文件构建映像,类似于 docker-compose 构建,但允许将所有服务作为单个请求的一部分并发构建。
它还支持从 HCL/JSON 文件中定制构建规则,从而实现更好的代码重用和不同的目标组。bake 的设计处于非常早期的阶段,我们正在寻找来自用户的反馈。
1.6. 命令
- docker buildx
- docker buildx bake
- docker buildx build
- docker buildx create
- docker buildx du
- docker buildx imagetools
- docker buildx imagetools create
- docker buildx imagetools inspect
- docker buildx inspect
- docker buildx install
- docker buildx ls
- docker buildx prune
- docker buildx rm
- docker buildx stop
- docker buildx uninstall
- docker buildx use
- docker buildx version