当前位置:首页>Linux>云原生镜像标准化实战:如何构建 linux/amd64&linux/arm64 多架构镜像

云原生镜像标准化实战:如何构建 linux/amd64&linux/arm64 多架构镜像

  • 2026-10-11 06:37:03
云原生镜像标准化实战:如何构建 linux/amd64&linux/arm64 多架构镜像

1 背景

2 解决方案

     2.1 QEMU

     2.2 Multiple platform nodes

     2.3 交叉编译buildx

          2.3.1 安装buildx

          2.3.2 部署Harbor

          2.3.3 配置buildx环境

          2.3.4 编写Dockerfile

          2.3.5 构建镜像并测试


1、背景

最近在一个国产化项目中遇到了这样一个场景,在同一个 Kubernetes 集群中的节点是混合架构的,也就是说,其中某些节点的 CPU 架构是 x86 的,而另一些节点是 ARM 的。

为了让我们的镜像在这样的环境下运行,一种最简单的做法是根据节点类型为其打上相应的标签,然后针对不同的架构构建不同的镜像,比如 demo:v1-amd64 和 demo:v1-arm64,然后还需要写两套 YAML:一套使用 demo:v1-amd64 镜像,并通过亲和性或 nodeSelector 选择 x86 的节点,另一套使用 demo:v1-arm64 镜像,并通过亲和性或 nodeSelector 选择 ARM 的节点。

很显然,这种做法不仅非常繁琐,而且管理起来也相当麻烦,如果集群中还有其他架构的节点,那么维护成本将成倍增加。

2 解决方案

(1)什么是多架构镜像?

多架构镜像并不是把多个架构的程序打包在一个镜像里,而是通过 Docker Manifest 清单,给同一个镜像标签绑定多个不同 CPU 架构(linux/amd64、linux/arm64)的独立镜像。

当在不同架构服务器拉取镜像时,Docker 会自动识别当前硬件架构,下载对应架构的镜像文件,实现一个镜像地址,全平台通用。

典型场景:

    • Intel 云服务器(amd64)、苹果 M 系列 / 鲲鹏服务器(arm64)以及 C86 架构混合集群部署

    • 国产化信创服务器兼容、边缘端 ARM 设备统一镜像交付

    • 开源项目、公共镜像实现一次构建,多平台分发

    (2)三种解决方案

    1)在内核中使用 QEMU 仿真支持

    2)直接在对应平台的硬件上构建镜像, 所以需要准备各个平台的主机。因为此方法门槛比较高, 所以并不常使用。

    3)使用 Dockerfile 中的多阶段构建, 交叉编译到不同的平台架构中。

    ① buildx方式

    ② docker manifest 

    ③ buildx 方式和 docker manifest 区别

            buildx

    Docker 生态中目前最优的构建方式,目前使用还需要在构建镜像的主机上额外部署插件,然后才能使用,未来预计会集成到docker服务中

    https://docs.docker.com/reference/cli/docker/buildx/

            docker manifest

    https://docs.docker.com/reference/cli/docker/manifest/ 

    官网提示:【实验功能旨在用于测试和反馈,因为它们功能或设计可能会在版本之间更改,恕不另行通知,或者可以在将来的版本中完全删除。】

    2.1 QEMU

    (1)说明

    QEMU 是最简单的构建跨平台镜像策略。它不需要对原有的 Dockerfile 进行任何更改, 会通过 binfmt_misc 这一 Linux 内核功能实现跨平台程序的执行。

    QEMU 是一个处理器模拟器, 可以模拟不同的 CPU 架构, 我们可以把它理解为是另一种形式的虚拟机。QEMU 模拟仿真过程中执行非本地架构的二进制文件。例如, 在 x86 主机上构建一个 ARM 镜像时, QEMU 可以模拟 ARM 环境并运行 ARM 二进制文件。

    binfmt_misc 是 Linux 内核的一个模块, 它允许用户注册可执行文件格式和相应的解释器。当内核遇到未知格式的可执行文件时, 会使用 binfmt_misc 查找与该文件格式关联的解释器(在这种情况下是 QEMU)并运行文件。

    QEMU 和 binfmt_misc 的结合使得通过 buildx 跨平台构建成为可能。这样我们就可以在一个架构的主机上构建针对其他架构的 Docker 镜像, 而无需拥有实际的目标硬件。

    (2)实验模拟

    1)下载qemu插件

    请提前下载好 qemu-aarch64-static.tar.gz

    2)安装qemu插件

    tar -zxvf qemu-aarch64-static.tar.gzsudo cp qemu-aarch64-static /usr/bin/chmod +x /usr/bin/qemu-aarch64-static

    3)注册qemu解释器

    docker run --rm --privileged multiarch/qemu-user-static:register --reset

    【上面输出是正确的】

    4)docker部署测试

    ## 部署一个ARM容器看看docker run -t \-v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static \arm64v8/ubuntu:20.04 uname -m
    docker run -d --name qq \-v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static \arm64v8/ubuntu:20.04 \tail -F /qq/qq

    (3)注意

    由于qemu本质上是使用x86指令对arm64指令集进行仿真(虚拟机),因此实际运行性能会比真机差很多 (可能耗时差几十甚至上百倍)。

    (3)注意

    由于qemu本质上是使用x86指令对arm64指令集进行仿真(虚拟机),因此实际运行性能会比真机差很多 (可能耗时差几十甚至上百倍)。

    非特殊情况不建议这么使用

    2.2 Multiple platform nodes

    使用多个不同架构的节点来运行业务,x86架构运行x86的业务,ARM架构运行ARM架构业务。

    这也是多架构解决方案之一,也是笨重的方法,不在本次讨论范围内

    2.3 交叉编译buildx

    2.3.1 安装buildx

    (1)说明

    在构建镜像时,是通过设置 --platform 参数来指定目标平台的。例如, linux/amd64 、 linux/arm64 或 darwin/amd64 。

    默认的构建驱动程序不支持并发多平台构建,一次只能针对一个平台进行构建,x86_64平台只能构建x86_64镜像,ARM平台只能构建ARM镜像。

    对多个平台进行构建(例如 --platform=linux/amd64,linux/arm64 ),则需要创建构建器(builder)。

    要使用不同的驱动程序,需要使用 Docker Buildx。 Buildx 是下一代构建客户端,它提供与 docker build 命令类似的用户体验,同时支持其他功能,而且未来功能会更多。

    (2)环境说明

    内核版本:3.10.0-957.el7.x86_64

    系统版本:CentOS Linux release 7.6.1810

    docker版本:Docker version 20.10.1

    网络环境:主机需要联网

    docker版本要求:要安装并使用 buildx,需要 Docker Engine 版本号大于等于 19.03。

    备注:本次直接使用外网进行构建的,也可以使用内网环境,内网环境需要一些配置,可自行研究

    (3)下载安装

    #下载Buildx

    wget https://github.com/docker/buildx/releases/download/v0.14.0/buildx-v0.14.0.linux-amd64

    #创建目标文件夹

    mkdir -p $HOME/.docker/cli-plugins

    #移动文件

    mv buildx-v0.14.0.linux-amd64 $HOME/.docker/cli-plugins/docker-buildx

    #添加执行权限

    chmod +x ~/.docker/cli-plugins/docker-buildx

    #检查安装情况

    docker buildx version
    docker version

    2.3.2 部署Harbor

    (1)配置私有仓库

    确保构建的镜像都通过push,传到私有仓库中,这里的镜像是多架构的,所以Harbor的版本必须大于v2.0,否则会push失败,这里使用的版本是v2.2.2,满足要求。

    配置docker的仓库地址是Harbor的地址

    [root@localhost ~]# cat /etc/docker/daemon.json {    "oom-score-adjust": -1000,    "exec-opts": ["native.cgroupdriver=systemd"],    "log-driver": "json-file",    "log-opts": {    "max-size": "100m",    "max-file": "3"    },    "max-concurrent-downloads": 10,    "max-concurrent-uploads": 10,    "experimental": true,    "registry-mirrors": [       "https://7bezldxe.mirror.aliyuncs.com",       "http://hub-mirror.c.163.com",       "https://docker.mirrors.ustc.edu.cn",       "https://hub.docker.com"    ],    "insecure-registries": ["192.168.25.99"],    "storage-driver": "overlay2",    "storage-opts": [    "overlay2.override_kernel_check=true"    ]}[root@localhost ~]# 

    (2)创建项目

    2.3.3 配置buildx环境

    (1)配置私有仓库地址

    使用buildx构建镜像,配置仓库地址,除了配置 daemon.json 文件之外还需要配置 /etc/buildkitd.toml 文件

    [root@localhost ~]# cat /etc/buildkitd.tomldebug = true# insecure-entitlements allows insecure entitlements, disabled by default.insecure-entitlements = [ "network.host", "security.insecure" ]# optionally mirror configuration can be done by defining it as a registry.[registry."192.168.25.99"]  http = true  insecure = true[root@localhost ~]#

    (2)创建构建器

    ① 查看默认的构建器

    默认的构建器只有构建本主机架构的,没有构建其他架构的,如下所示:

    docker buildx ls

    ② 创建新的构建器

    #### 方式一(不建议创建时使用,排查问题时可这么使用):

    	docker buildx create --name builderx	docker buildx use builderx	docker buildx inspect --bootstrap

    #### 删除构建器:

    	docker buildx rm builderx

    #### 方式二(建议使用):

    若私有仓库非 https 的情况下需指定--driver-opt network=host 和 --config /etc/buildkit/buildkitd.toml 两个参数

    docker buildx create --use --bootstrap \  --name mybuilder-http \  --driver-opt network=host \  --driver docker-container \  --platform 'linux/arm64,linux/amd64,linux/amd64/v2,linux/arm/v7,linux/arm/v6,linux/amd64/v3,linux/386' \  --config /etc/buildkitd.toml

    #### 注意:

    --name:构建器名称,必填

    --driver:构建器驱动程序,默认为 docker-container

    常用的有两种驱动:docker 与 docker-container:

    --driver docker,表示使用绑定到 dockerd 的 BuildKit 工具来进行构建操作。但是,由于绑定到 dockerd 的 Buildkit 库使用不同的存储组件,所以该驱动未支持某些特性。比如说,--platform只能指定一个参数,不支持多平台同时构建。

    --driver docker-container,表示使用容器运行 BuildKit 工具,在此容器中执行构建任务。而该构建方式产生的镜像,无法直接通过 docker images 查看,需要指定 -output 选项来导出。

    --driver-opt:驱动程序选项,默认值是 moby/buildkit

    创建后会生成一个容器,可查看容器的详细信息

    ③ 查看创建的构建器

    docker buildx inspect mybuilder-http  --bootstrap
    docker buildx ls

    【* 表示当前正在使用该构建器构建镜像】

    2.3.4 编写Dockerfile

    (1)在这个构建机上登录Harbor

    登录Harbor,不然会push失败,多架构镜像构建,默认会推送到仓库中,不会在本地的docker images中看得到

    默认会push到dockerhub中,我们设置了私有仓库,所以会push到私有仓库中

    (2)编写dockerfile

    [root@localhost buildx]# cat Dockerfile FROM --platform=$TARGETPLATFORM nginxRUN uname -m > /usr/share/nginx/html/index.htmlRUN uname -m >> /usr/share/nginx/html/index.html[root@localhost buildx]# 

    -----------------------------------------------------------------

    TARGETPLATFORM:是 BuildKit 提供的全局变量,是构建镜像的目标架构平台

    (3)详解

    BuildKit 后端预定义了一组 ARG 全局变量(共 8 个)可供使用, 其定义和说明如下:

    在构建镜像时, BuildKit 会将当前所在平台信息传递给 Dockerfile 中的 BUILDPLATFORM 参数(如 linux/arm64)。

    我们在docker buildx build时,会使用--platform 参数,docker通过 --platform 参数传递的 linux/arm64,linux/amd64 镜像目标平台列表会依次传递给 TARGETPLATFORM 变量,这样就生成了我们想要的多架构镜像了。

    2.3.5 构建镜像并测试

    (1)构建镜像

    ① 构建镜像

    docker buildx build --platform linux/amd64,linux/arm64 -t 192.168.25.99/test/nginx-0513:v1 . --push

    ② 注意事项

    在构建时必须添加 --push 或 --load 参数,否则会得到警告WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load。意思是构建结果只保存在缓存中,不会落到主机上,且即使构建完毕,使用 docker images 也不会看到,使用 --push 可以将镜像推送到远程仓库,使用 --load 可以将镜像保存在本地。

    需要注意的是,若参数添加的是 --load 不是 --push,且--platform 后面跟了多个平台,如 --platform=linux/amd64,linux/arm64,linux/arm/v7,那么还是会得到报错ERROR: docker exporter does not currently support exporting manifest lists,这是因为本地无法保存多个同名的镜像导致的。

    所以如果要保存构建出的多个平台的镜像到本地,就得分多次执行命令,每次只在 --platform 后添加一个平台,并且每次的 --tag 后面的镜像名称都不同。

    例如为三个平台构建了镜像,就得分三次执行命令:

    docker buildx build \    --builder=mybuilder-http \    --platform=linux/amd64 \    --tag=nginx_amd64:latest \    --load .
    docker buildx build \    --builder=mybuilder-http \    --platform=linux/arm/v7 \    --tag=nginx_arm_v7:latest \    --load .
    docker buildx build \    --builder=mybuilder-http \    --platform=linux/arm64 \    --tag=nginx_arm64:latest \    --load .

    (2)检查Harbor上镜像

    我们的镜像支持多平台,拉取镜像的时候会根据我们的平台自动下载对应平台镜像。

    默认x86主机上下载的镜像是amd64

    默认ARM主机上下载的镜像是arm64

    (3)查看镜像详情

    docker buildx imagetools inspect 192.168.25.99/test/nginx-0513:v1

    (4)本地是没有新构建的镜像的

    (5)测试

    (6)最后完结撒花

    最新文章

    随机文章