使用 buildx 构建多平台镜像
安装 docker engine
在 Ubuntu 上安装 docker engine
- 卸载非官方版本 docker engine,包含如下包
- docker.io
- docker-compose
- docker-doc
- podman-docker
# docker engine 依赖 containerd 和 runc ,因此需要一起卸载,避免冲突
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove -y $pkg; done
- 通过 apt 仓库安装
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Enable docker
systemctl enable --now docker
构建多平台镜像
docker 插件工具 buildx 可以支持构建跨平台镜像,在构建镜像时通过 --platform
参数指定要构建的平台,例如:linux/amd64
、linux/arm64
。
构建策略
根据不同场景,构建多平台镜像可以支持以下三种不同的策略。
- 使用
QEMU
模拟器在内核内支持。 - 使用多平台本地节点构建。
- 在
Dockerfile
内使用不同的阶段交叉编译。(需要源码支持)
使用 QEMU 策略构建
使用 QEMU 方式构建多平台镜像是比较方便和容易的做法,这种方法不需要修改本身的 Dockerfile
文件。他是通过 BuildKit
自动检测主机支持的不同的架构,并通过 binfmt_misc
自动加载对应的平台库去构建。在 QEMU
构建其他平台镜像相对于构建本地架构的镜像要慢很多,同时会占用大量的性能开销。
对于 QEMU 这种构建方式,需要内核 4.8
及以后的版本以及 2.1.7
及以后版本的 binfmt-support
。
- 检测主机是否支持
# 查看主机配置中 `flags` 是否为 `F`
grep flags /proc/sys/fs/binfmt_misc/qemu-*
# docker desktop 已经预安装了 `binfmt_misc`,其他安装方式需要通过 `tonistiigi/binfmt` 镜像安装
docker run --privileged --rm tonistiigi/binfmt --install all
开始构建镜像
创建 builder
使用 docker buildx ls
指令查看 builder
docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default * docker
default default running v0.11.6 linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
上面显示的是默认的内置构建 drive,使用的是 docker driver , 他直接是用 docker engine 来构建镜像。
接下来创建一个 docker-container
drive 的 builder
,这个 builder
能提供一些更加复杂的特性,例如多平台构建以及更加高级的缓存导出。
docker buildx create --name mybuilder --bootstrap --use
# 再次检查
docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running v0.12.1 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default docker
default default running v0.12.1 linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
示例
创建如下 Dockerfile
# syntax=docker/dockerfile:1
FROM alpine:3.16
RUN apk add curl
构建多平台镜像
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t <username>/<image>:latest --push .
...
#16 exporting to image
#16 exporting layers
#16 exporting layers 0.5s done
#16 exporting manifest sha256:71d7ecf3cd12d9a99e73ef448bf63ae12751fe3a436a007cb0969f0dc4184c8c 0.0s done
#16 exporting config sha256:a26f329a501da9e07dd9cffd9623e49229c3bb67939775f936a0eb3059a3d045 0.0s done
#16 exporting manifest sha256:5ba4ceea65579fdd1181dfa103cc437d8e19d87239683cf5040e633211387ccf 0.0s done
#16 exporting config sha256:9fcc6de03066ac1482b830d5dd7395da781bb69fe8f9873e7f9b456d29a9517c 0.0s done
#16 exporting manifest sha256:29666fb23261b1f77ca284b69f9212d69fe5b517392dbdd4870391b7defcc116 0.0s done
#16 exporting config sha256:92cbd688027227473d76e705c32f2abc18569c5cfabd00addd2071e91473b2e4 0.0s done
#16 exporting manifest list sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48 0.0s done
#16 ...
#17 [auth] <username>/<image>:pull,push token for registry-1.docker.io
#17 DONE 0.0s
#16 exporting to image
#16 pushing layers
#16 pushing layers 3.6s done
#16 pushing manifest for docker.io/<username>/<image>:latest@sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48
#16 pushing manifest for docker.io/<username>/<image>:latest@sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48 1.4s done
#16 DONE 5.6s
> <username> must be a valid Docker ID and <image> and valid repository on Docker Hub.
> The --platform flag informs buildx to create Linux images for AMD 64-bit, Arm 64-bit, and Armv7 architectures.
> The --push flag generates a multi-arch manifest and pushes all the images to Docker Hub.
验证
进入 docker hub 仓库检查刚刚推送的镜像是否支持linux/amd64,linux/arm64,linux/arm/v7
平台,并在 arm 架构机器上运行上述镜像,得到如下结果:
docker run --rm docker.io/<username>/<image>:latest@sha256:723c22f366ae44e419d12706453a544ae92711ae52f510e226f6467d8228d191 uname -m
armv7l