构建多平台Docker镜像

         利用 Docker 19.03 以上版本引入的插件 buildx[4],可以很轻松地构建多平台 Docker 镜像。buildx 是 docker build ... 命令的下一代替代品,它利用 BuildKit[5] 的全部功能扩展了 docker build 的功能。

1、启用buildx插件

要想使用 buildx,首先要确保 Docker 版本不低于 19.03,同时还要通过设置环境变量 DOCKER_CLI_EXPERIMENTAL 来启用。可以通过下面的命令来为当前终端启用 buildx 插件:

export DOCKER_CLI_EXPERIMENTAL=enabled

验证是否开启:

docker buildx version

注:如果在系统上设置环境变量DOCKER_CLI_EXPERIMENTAL不生效(比如Arch Linux),可以通过源代码编译:

export DOCKER_BUILDKIT=1
docker build --platform=local -o . git://github.com/docker/buildx
mkdir -p ~/.docker/cli-plugins && mv buildx ~/.docker/cli-plugins/docker-buildx

2、启用binfmt_misc

        如果你使用的是 Docker 桌面版(MacOS 和 Windows),默认已经启用了 binfmt_misc,可以跳过这一步。

        如果你使用的是 Linux,需要手动启用 binfmt_misc。大多数 Linux 发行版都很容易启用,不过还有一个更容易的办法,直接运行一个特权容器,容器里面写好了设置脚本:

docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d

CentOS用户建议Linux内核升级到4.x以上。

验证binfmt_misc是否开启:

ls -al /proc/sys/fs/binfmt_misc/


total 0
drwxr-xr-x 2 root root 0 4月  28 20:19 .
dr-xr-xr-x 1 root root 0 4月  28 18:44 ..
-rw-r--r-- 1 root root 0 4月  28 20:19 qemu-aarch64
-rw-r--r-- 1 root root 0 4月  28 20:19 qemu-arm
-rw-r--r-- 1 root root 0 4月  28 20:19 qemu-ppc64le
-rw-r--r-- 1 root root 0 4月  28 20:19 qemu-s390x
--w------- 1 root root 0 4月  28 20:19 register
-rw-r--r-- 1 root root 0 4月  28 20:19 status

验证是否启用了相应的处理器:

cat /proc/sys/fs/binfmt_misc/qemu-aarch64


enabled
interpreter /usr/bin/qemu-aarch64
flags: OCF
offset 0
magic 7f454c460201010000000000000000000200b7
mask ffffffffffffff00fffffffffffffffffeffff

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

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

先创建一个新的构建器:

docker buildx create --use --name mybuilder   #创建新的构建器
docker buildx inspect mybuilder --bootstrap   #启动构建器

创建的多平台构建器如下:

[+] Building 118.9s (1/1) FINISHED                                              
 => [internal] booting buildkit                                          118.8s
 => => pulling image moby/buildkit:buildx-stable-1                       117.6s
 => => creating container buildx_buildkit_mybuilder0                       1.3s
Name:   mybuilder
Driver: docker-container

Nodes:
Name:      mybuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

查看当前使用的构建器及构建器支持的 CPU 架构,可以看到支持很多 CPU 架构:

docker buildx ls


NAME/NODE    DRIVER/ENDPOINT             STATUS  PLATFORMS
mybuilder *  docker-container                    
  mybuilder0 unix:///var/run/docker.sock running linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
default      docker                              
  default    default                     running linux/amd64, linux/386, linux/arm64, linux/ppc64le, linux/s390x, linux/arm/v7, linux/arm/v6

4、构建多平台镜像

简单的 golang 程序源码:

gedit ./hello.go
package main

import (

        "fmt"
        "runtime"
)

func main() {
        fmt.Printf("Hello, %s!\n", runtime.GOARCH)
}

创建一个 Dockerfile 将该应用容器化:

gedit Dockerfile


FROM golang:alpine AS builder
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o hello .

FROM alpine
RUN mkdir /app
WORKDIR /app
COPY --from=builder /app/hello .
CMD ["./hello"]

        这是一个多阶段构建 Dockerfile,使用 Go 编译器来构建应用,并将构建好的二进制文件拷贝到 alpine 镜像中。

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

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

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

        背后的原理也很简单,之前已经提到过了,buildx 会通过 QEMUbinfmt_misc 分别为 3 个不同的 CPU 架构(arm,arm64 和 amd64)构建 3 个不同的镜像。构建完成后,就会创建一个 manifest list[7],其中包含了指向这 3 个镜像的指针。

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

docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm -o type=docker .


docker buildx build -t yangchuansheng/hello-arch --platform=linux/arm64 -o 
type=docker .


docker buildx build -t yangchuansheng/hello-arch --platform=linux/amd64 -o type=docker .

5、测试多平台镜像

        由于之前已经启用了 binfmt_misc,现在我们就可以运行任何 CPU 架构的 Docker 镜像了,因此可以在本地系统上测试之前生成的 3 个镜像是否有问题。

        首先列出每个镜像的 digests

docker buildx imagetools inspect yangchuansheng/hello-arch


Name:      docker.io/yangchuansheng/hello-arch:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:ec55f5ece9a12db0c6c367acda8fd1214f50ee502902f97b72f7bff268ebc35a

Manifests:
  Name:      docker.io/yangchuansheng/hello-arch:latest@sha256:38e083870044cfde7f23a2eec91e307ec645282e76fd0356a29b32122b11c639
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm/v7

  Name:      docker.io/yangchuansheng/hello-arch:latest@sha256:de273a2a3ce92a5dc1e6f2d796bb85a81fe1a61f82c4caaf08efed9cf05af66d
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64

  Name:      docker.io/yangchuansheng/hello-arch:latest@sha256:8b735708d7d30e9cd6eb993449b1047b7229e53fbcebe940217cb36194e9e3a2
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64

        运行每一个镜像并观察输出结果:

docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:38e083870044cfde7f23a2eec91e307ec645282e76fd0356a29b32122b11c639

Hello, arm!


docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:de273a2a3ce92a5dc1e6f2d796bb85a81fe1a61f82c4caaf08efed9cf05af66d

Hello, arm64!


docker run --rm docker.io/yangchuansheng/hello-arch:latest@sha256:8b735708d7d30e9cd6eb993449b1047b7229e53fbcebe940217cb36194e9e3a2

Hello, amd64!

参考链接:

跨平台构建 Docker 镜像新姿势,x86、arm 一把梭 - 云+社区 - 腾讯云

脚注

[1]

QEMU: https://www.wikiwand.com/zh-hans/QEMU

[2]

binfmt_misc: https://en.wikipedia.org/wiki/Binfmt_misc

[3]

chroot: https://en.wikipedia.org/wiki/Chroot

[4]

buildx: https://github.com/docker/buildx

[5]

BuildKit: https://github.com/moby/buildkit

[6]

Docker Hub: https://hub.docker.com/

[7]

manifest list: https://docs.docker.com/engine/reference/commandline/manifest/

[8]

Building Multi-Arch Images for Arm and x86 with Docker Desktop: https://engineering.docker.com/2019/04/multi-arch-images/

[9]

Getting started with Docker for Arm on Linux: https://engineering.docker.com/2019/06/getting-started-with-docker-for-arm-on-linux/

[10]

Leverage multi-CPU architecture support: https://docs.docker.com/docker-for-mac/multi-arch/

原文出处及转载信息见文内详细说明,如有侵权,请联系[email protected] 删除。

  • Building Multi-Arch Images for Arm and x86 with Docker Desktop[8]
  • Getting started with Docker for Arm on Linux[9]
  • Leverage multi-CPU architecture support[10]

你可能感兴趣的:(docker,运维,容器)