使用 buildx 构建多平台 Docker 镜像

文章目录

背景

回顾一下当前跨 CPU 架构编译程序的不同方法。

  • 方法一:直接在目标硬件上编译

  • 方法二:模拟目标硬件

  • 方法三:通过 binfmt_misc 模拟目标硬件的用户空间

  • 方法四:使用交叉编译器

  • 新方案:

    ​ =>使用buildx构建多平台 Docker 镜像(无需修改dockerfile)

快速开始

1.查看buildx插件(要求docker大于19.03)

20.10.7是默认支持的

docker buildx version
github.com/docker/buildx v0.5.1-docker 11057da37336192bfc57d81e02359ba7ba848e4a
//如果提示docker: 'buildx' is not a docker command.  需要看下docker版本

2.Docker for Linux 不支持构建 arm 架构镜像,我们可以运行一个新的容器让其支持该特性

启用 binfmt_misc

//可以通过运行一个特权 Docker 容器来更方便的设置启用 binfmt_misc
docker run --rm --privileged tonistiigi/binfmt:latest --install all


//查看支持的处理器
ls -al /proc/sys/fs/binfmt_misc/
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-aarch64
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-arm
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-mips64
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-mips64el
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-ppc64le
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-riscv64
-rw-r--r-- 1 root root 0 Nov  6 08:10 qemu-s390x


//验证是否启用了指定的处理器 enabled即启用成功
cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64
flags: OCF
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff

3.从默认的构建器切换到多平台构建器

由于 Docker 默认的 builder 实例不支持同时指定多个 --platform,我们必须首先创建一个新的 builder 实例

Docker 默认会使用不支持多 CPU 架构的构建器,我们需要手动切换。

#由于 Docker 默认的 builder 实例不支持同时指定多个 --platform,我们必须首先创建一个新的 builder 实例。
#同时由于国内拉取镜像较缓慢,我们可以使用配置了 镜像加速地址 的 dockerpracticesig/buildkit:master 镜像替换官方镜像。

# 创建适用于国内环境的构建器
docker buildx create --use --name=mybuilder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master

docker buildx inspect mybuilder --bootstrap

#查看构建器
docker buildx ls

#切换构建器
docker buildx use mybuilder-cn 

4.可以使用 buildx 构建一个支持 arm、arm64 和 amd64 多架构的 Docker 镜像了

当前目录下新建一个dockerfile

FROM --platform=$TARGETPLATFORM alpine
RUN uname -a > /os.txt
CMD cat /os.txt

5.本地生成镜像

#本地保存,只能为每个架构生成一个镜像,不能合并成一个镜像
docker buildx build -t myname/hello-arm --platform=linux/arm -o type=docker .
docker buildx build -t myname/hello-arm64 --platform=linux/arm64 -o type=docker .
docker buildx build -t myname/hello-amd64 --platform=linux/amd64 -o type=docker .
# 查看镜像信息
docker buildx imagetools inspect myname/hello-arch

#运行
docker run -it --rm myname/hello-arm64

docker save -o hello-arm64.tar myname/hello-arm64

docker load -i hello-arm64.tar

架构相关变量

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

使用举例

例如我们要构建支持 linux/arm/v7linux/amd64 两种架构的镜像。假设已经生成了两个平台对应的二进制文件:

  • bin/dist-linux-arm
  • bin/dist-linux-amd64

那么 Dockerfile 可以这样书写:

FROM scratch

# 使用变量必须申明
ARG TARGETOS

ARG TARGETARCH

COPY bin/dist-${TARGETOS}-${TARGETARCH} /dist

ENTRYPOINT ["dist"]

原理分析

可以使用 buildx 构建一个支持 arm、arm64 和 amd64 多架构的 Docker 镜像了,同时将其推送到 Docker Hub

就可以通过 docker pull mirailabs/hello-arch 拉取刚刚创建的镜像了,Docker 将会根据你的 CPU 架构拉取匹配的镜像。

docker buildx build -t xxx/hello-arch --platform=linux/arm,linux/arm64,linux/amd64 . --push

背后的原理也很简单,

buildx 会通过 QEMUbinfmt_misc 分别为 3 个不同的 CPU 架构(arm,arm64 和 amd64)构建 3 个不同的镜像。

构建完成后,就会创建一个 manifest list,其中包含了指向这 3 个镜像的指针。


如果想将构建好的镜像保存在本地,可以将 type 指定为 docker,但必须分别为不同的 CPU 架构构建不同的镜像,不能合并成一个镜像,即:

docker buildx build -t xxx/hello-arm --platform=linux/arm -o type=docker .
docker buildx build -t xxx/hello-arm64 --platform=linux/arm64 -o type=docker .
docker buildx build -t xxx/hello-amd64 --platform=linux/amd64 -o type=docker .

总结

使用 buildx,我们无需对 Dockerfile 进行任何修改,就可以创建支持多种 CPU 架构的 Docker 镜像,然后将其推送到 Docker Hub。任何安装了 Docker 的系统都可以拉取到与它的 CPU 架构相对应的镜像。

未来 buildx 可能会成为 docker build 命令的一部分,最终所有上面提到的功能都会变成默认的功能,下沉到基础设施中交叉编译程序的做法将会变成远古时代的愚蠢行为。

参考

具体使用:

https://github.com/docker/buildx

参考:

https://fuckcloudnative.io/posts/multiarch-docker-with-buildx/

https://docker-practice.github.io/zh-cn/buildx/multi-arch-images.html

https://www.kancloud.cn/docker_practice/docker_practice/2002051

docker从入门到实践 :https://github.com/yeasy/docker_practice

上一篇:1.4WEB API 路由配置及参数传输


下一篇:软件安装 -> CMake