使用 docker buildx 构建跨平台镜像

news2025/2/23 21:47:30

buildx是Docker官方提供的一个构建工具,它可以帮助用户快速、高效地构建Docker镜像,并支持多种平台的构建。使用buildx,用户可以在单个命令中构建多种架构的镜像,例如x86和arm架构,而无需手工操作多个构建命令。此外buildx还支持Dockerfile的多阶段构建和缓存,这可以大大提供镜像构建的效率和速度。

buildx是一个管理Docker构建的CLI插件,底层使用了BuildKit扩展了Docker构建功能。

BuildKit是Docker官方提供一个高性能构建引擎,可以用来替代Docker原有的构建引擎。相比于原有引擎,BuildKit具有更快的构建速度、更高的并行性、更少的资源占用和更好的安全性。

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

跨平台镜像构建策略

builder支持是那种不通策略构建跨平台镜像。

在内核中使用QEMU仿真支持

如果你正在使用Docker Desktop,则已经支持了QEMU,QEMU是最简单的构建跨平台镜像策略。它不需要对原有的Dockerfile进行任何更改,BuildKit会通过binfmt_misc这一Linux内核功能实现跨平台程序的执行。

工作原理:

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

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

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

虽然Docker Desktop预配置了binfmt_misc对其他平台的支持,但对于其他版本Docker,你可能需要使用tonistiigi/binfmt镜像启动一个特权容器来进行支持。

docker run --privileged --rm tonistiigi/binfmt --install all

运行此命令会安装不同架构的解释器程序,即/usr/bin目录下的qemu模拟器:

 在我们编译服务器上加载了binfmt_misc模块:

docker buildx使用qemu的作用

Docker Buildx 是 Docker 的一个实验性功能,它扩展了 Docker 的构建功能,包括使用多节点、qemu 等。QEMU 是一个开源的虚拟机软件,它可以模拟不同的 CPU 和其他硬件,使得我们可以在一个操作系统上构建另一种操作系统的镜像。

使用 Docker Buildx 的 qemu 功能,可以帮助我们构建面向多种不同架构(如 ARM、MIPS 等)的 Docker 镜像。

以下是一个简单的例子,展示如何使用 Docker Buildx 和 QEMU 来构建一个面向 ARM 架构的 Docker 镜像:

# 创建一个新的 buildkit 实例
docker buildx create --name mybuilder --use
 
# 启动 buildkit 实例
docker buildx start mybuilder
 
# 启用 QEMU 驱动支持
docker buildx inspect --bootstrap
 
# 构建一个面向 ARM 架构的 Docker 镜像
docker buildx build --platform linux/arm/v7 -t myimage:latest .

在这个例子中,--platform 参数指定了我们想要构建的目标平台是 ARM v7。这样,Docker 会使用 QEMU 来模拟一个 ARM 环境,并在 x86 架构的机器上构建出面向 ARM 架构的 Docker 镜像。

binfmt_misc文件系统

binfmt-misc是Linux内核提供的一种类似windows上文件关联的功能,但比文件关联更强大的是,它不仅可以根据文件后缀名判断,还可以根据文件内容(Magic Bytes)使用不同的程序打开。一个典型的使用场景就是:使用qemu运行其他架构平台上的二进制文件。

开启binfmt-misc

临时开启可以使用以下命令:

$ sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc

这种方式重启后会失效,如果想长期生效,可以在/etc/fstab文件中增加一行:

none  /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0

可以使用以下命令检查开启是否成功:

$ mount | grep binfmt_misc
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
$ ls -l /proc/sys/fs/binfmt_misc
总用量 0
--w------- 1 root root 0 2月   5 22:55 register
-rw-r--r-- 1 root root 0 2月   5 22:55 status

先准备一个arm64架构的程序,执行后发现有报错:

bash: ./go-test:无法执行二进制文件: 可执行文件格式错误

现在,我们执行一下apt install qemu-user-binfmt命令,然后再运行上面的arm64程序,发现能正常运行了。安装qemu-user-binfmt后,会在/proc/sys/fs/binfmt_misc目录下创建若干个文件,其中就有一个qemu-aarch64,来看一下这个文件的内容:

root@ubuntu:/proc/sys/fs/binfmt_misc# cat qemu-aarch64 
enabled
interpreter /usr/bin/qemu-aarch64-static
flags: OC
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff
root@ubuntu:/proc/sys/fs/binfmt_misc#

这个文件描述的是规则文件:

第一行enabled表示该规则启用 ;

第二行 interpreter /usr/bin/qemu-aarch64-static表示使用/usr/bin/qemu-aarch64-static来执行二进制文件;

第三行:OC表示运行的标志位,具体含义如下:

 P: 表示perserve-argv,这意味着在调用模拟器时,原始的参数(argv)将被保留。这对于默写程序在运行时需要知道它们自己的名称(即argv[0])的情况很有用

O: 表示offset,这意味着在启动模拟器之前,需要从二进制文件中读取一个偏移量,这个偏移量将作为模拟器的一个参数

C:表示credentials,这意味着模拟器将使用于原始程序相同的用户ID和组ID运行,这有助于确保模拟器在运行时与原始程序相同的权限。

第四行:offset 0表示从0便宜值开始读取文件;

第五行: magic 7f454c460201010000000000000000000200b700表示要匹配的模数字节;

arm64架构的ELF文件头部的magic字段如下,也就是说binfmt_misc文件系统可以根据ELF文件中的magic字段来决定此文件使用哪个架构的模拟器运行:

下面是两个不同架构的 

mips架构的:  7f454c4601020100000000000000000000020008
arm64架构的:7f454c460201010000000000000000000200b700

第六行:mask ffffffffffffff00fffffffffffffffffeffffff 表示字节掩码,用哦过来忽略掉文件中的一些不重要的字节。

在x86_64系统中运行arm64架构的Docker镜像

现在我们用docker命令运行一个arm64的镜像:

$ docker run -it arm64v8/ubuntu bash
Unable to find image 'arm64v8/ubuntu:latest' locally
latest: Pulling from arm64v8/ubuntu
005e2837585d: Pull complete 
Digest: sha256:ba545858745d6307f0d1064d0d25365466f78d02f866cf4efb9e1326a4c196ca
Status: Downloaded newer image for arm64v8/ubuntu:latest
standard_init_linux.go:207: exec user process caused "no such file or directory"

通过一番探索之后,发现只要执行下命令:apt install qemu-user-static,再启动docker容器就正常了。

使用 Dockerfile 中的多阶段交叉构建

交叉编译的复杂度不在于Docker,而是取决于程序本身。比如Go程序就很容易实现交叉编译,只需要在使用go build构建程序时执行GOOS、GOARCH两个环境变量即可实现。

创建builder

要使用buildx构建跨 平台镜像,我们需要先创建一个builder,可以翻译为构建器。

使用docker buildx ls命令可以查看builder列表:

root@ubuntu:/proc# docker buildx ls
NAME/NODE         DRIVER/ENDPOINT             STATUS  PLATFORMS
mybuild *         docker-container                    
  mybuild0        unix:///var/run/docker.sock running linux/arm64*, linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386
vigilant_hugle    docker-container                    
  vigilant_hugle0 unix:///var/run/docker.sock stopped 
default           docker                              
  default         default                     running linux/amd64, linux/386

*号表示当前正在使用的builder,当我们运行docker build命令时就是在使用此builder构建镜像。第二列的DRIVER/ENDPOINT表示使用的驱动程序。buildx支持以下几种驱动程序:

  • docker:使用捆绑到Docker守护进程中的BuildKit库,就是安装Docker后默认的BuildKit。
  • docker-container:使用Docker新创建一个专用的BuildKit容器。
  • kubernetes: 在kubernetes集群中创建一个BuildKit Pod。
  • remote:直接连接到手工管理的BuildKit守护进程。

因为使用docker驱动程序的默认builder不支持使用单条命令(默认builder的--platform参数只接收单个值)构建跨平台镜像,所以我们需要使用docker-container驱动创建一个新的builder。

命令语法如下:

$ docker buildx create --name=<builder-name> --driver=<driver> --driver-opt=<driver-options>

参数含义如下;

--name: 构建起名称,必填。

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

--driver-opt:驱动程序选项,如选项--driver-opt=image=moby/buildkit:v0.11.3可以安装指定版本的BuildKit,默认值为moby/buildkit。

我们可以使用如下命令创建一个新的builder:

$ docker buildx create --name mybuilder
mybuilder

再次查看 builder 列表:

$ docker buildx ls
NAME/NODE       DRIVER/ENDPOINT             STATUS   BUILDKIT PLATFORMS
mybuilder *     docker-container
  mybuilder0    unix:///var/run/docker.sock inactive
default         docker
  default       default                     running  20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux               running  20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

 可以发现选中的构建起已经切换到了Mybuilder,如果没有选中,你需要手动使用docker buildx use mybuilder命令切换构建器。

启动 builder

 我们新创建的mybuilder当前状态为inactive,需要启动才能使用。

$ docker buildx inspect --bootstrap mybuilder
[+] Building 16.8s (1/1) FINISHED
 => [internal] booting buildkit                                                                                                                                  16.8s
 => => pulling image moby/buildkit:buildx-stable-1                                                                                                               16.1s
 => => creating container buildx_buildkit_mybuilder0                                                                                                              0.7s
Name:   mybuilder
Driver: docker-container

Nodes:
Name:      mybuilder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Buildkit:  v0.9.3
Platforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

inspect子命令用来检查构建起状态,使用--bootstrap参数可以启动mybuilder构建器,再次查看builder列表,mybuilder状态已经变成了running。

$ docker buildx ls
NAME/NODE       DRIVER/ENDPOINT             STATUS  BUILDKIT PLATFORMS
mybuilder *     docker-container
  mybuilder0    unix:///var/run/docker.sock running v0.9.3   linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default         docker
  default       default                     running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux               running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

其中PLATFORMS一列所展示的值

 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6 就是当前构建器所支持的所有平台了。

现在使用docker ps命令可以看到mybuilder构建器所对应的BuildKit容器已经启动。

$ docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS         PORTS                                NAMES
b8887f253d41   moby/buildkit:buildx-stable-1   "buildkitd"              4 minutes ago   Up 4 minutes                                        buildx_buildkit_mybuilder0

这个容器就是辅助我们构建跨平台镜像用的,不要手动删除它。

使用 builder 构建跨平台镜像 

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go .

docker buildx build 语法跟 docker build 一样, --platform 参数表示构建镜像的目标平台, -t 表示镜像的 Tag, . 表示上下文为当前目录。 

唯一不通的是对--platform参数的支持,docker build的--platform参数只支持传递一个平台信息,如--platform linux/arm64,也就是一次能构建单个平台的镜像。

而使用docker buildx build构建镜像则支持同时传递多个平台信息,中间使用英文逗号分隔,这样就实现了只用一条命令便可以构建多个跨平台镜像的功能。

执行以上命令后,我们将会得到一条警告:

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-container驱动程序指定输出,生成结果将只会保留在构建缓存中,使用--push可以将镜像推送到Docker Hub远程仓库,使用--load可以将镜像保存在本地。

这是因为我们新创建的mybuilder是启动了一个容器来运行BuildKit,它并不能直接将构建好的跨平台镜像输出到本机或推送到远程,必须要用户来手动指定输出位置。

我们可以尝试指定--load将镜像保存在本地主机。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --load
[+] Building 0.0s (0/0)
ERROR: docker exporter does not currently support exporting manifest lists

结果会得到一条错误日志。看来它并不支持将跨平台镜像输出到本地,这其实是因为传递了多个--platform的关系,如果--platform只传递了一个平台,则可以使用--load将构建好的镜像输出到本机。

那么我们就只能通过--push参数将跨平台镜像推送到远程仓库了。不过在此之前需要确保使用docker login完成登录。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --push

现在登录Docker Hub就可以看见推送上来的跨平台镜像了。

我们也可以使用imagestools来检查跨平台镜像的manifest信息,这条命令只能用来获取仓库中的image信息,本地的images无法查看。

$ docker buildx imagetools inspect jianghushinian/hello-go
Name:      docker.io/jianghushinian/hello-go:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:51199dadfc55b23d6ab5cfd2d67e38edd513a707273b1b8b554985ff562104db

Manifests:
  Name:      docker.io/jianghushinian/hello-go:latest@sha256:8032a6f23f3bd3050852e77b6e4a4d0a705dfd710fb63bc4c3dc9d5e01c8e9a6
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64

  Name:      docker.io/jianghushinian/hello-go:latest@sha256:fd46fd7e93c7deef5ad8496c2cf08c266bac42ac77f1e444e83d4f79d58441ba
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64

 

可以看到,这个跨平台镜像包含了两个目标平台的镜像,分别是linux/arm64和linux/amd64。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python从入门到放弃——整数类型变量

变量 前言 上一篇文章中我们学习了Print函数&#xff0c;并且深入的理解了Print函数的各个参数。明确了应该如何利用各种参数来实现我们想输出的效果。那么现在让我们来学习一下变量这一个知识点。 什么是变量 变量&#xff0c;作为编程中的核心概念之一&#xff0c;其重要性…

计算机的错误计算(二十二)

摘要 计算机的错误计算&#xff08;十九&#xff09;展示了计算机的一个错误计算&#xff1a;本应该为 0的算式的结果不为0. 那么&#xff0c;增加计算精度&#xff0c;能确定是0吗&#xff1f;不一定。 计算机的错误计算&#xff08;十九&#xff09;展示了计算机对 的错误计…

74. 搜索二维矩阵【二分法】【C++】

题目描述 搜索二维矩阵 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&…

海外金融机构银行保险证券数字化转型营销销售数字化成功案例讲师培训师讲授开户销售营销客户AI人工智能创新思维

金融机构需要数字营销的主要原因 数字银行、直接存款和移动网络的兴起让客户无需前往当地分行即可轻松办理银行业务。这些举措不仅提升了用户体验&#xff0c;也迫使银行向数字化世界迈进。 金融服务公司需要在数字营销渠道上保持稳固的地位&#xff0c;以免落后于大型机构。…

字符串相似度算法完全指南:编辑、令牌与序列三类算法的全面解析与深入分析

在自然语言处理领域&#xff0c;人们经常需要比较字符串&#xff0c;这些字符串可能是单词、句子、段落甚至是整个文档。如何快速判断两个单词或句子是否相似&#xff0c;或者相似度是好还是差。这类似于我们使用手机打错一个词&#xff0c;但手机会建议正确的词来修正它&#…

磁盘分区工具 -- 傲梅分区助手 v10.4.1 技术员版

软件简介 傲梅分区助手是一款功能强大的磁盘分区工具&#xff0c;它专为Windows系统设计&#xff0c;帮助用户更高效地管理他们的硬盘。该软件支持多种分区操作&#xff0c;包括创建、格式化、调整大小、移动、合并和分割分区。此外&#xff0c;它还提供了复制硬盘和分区的功能…

【手机取证】如何使用360加固助手给apk加固

文章关键词&#xff1a;手机取证、电子数据取证、数据恢复 一、前言 APP加固是对APP代码逻辑的一种保护。原理是将应用文件进行某种形式的转换&#xff0c;包括不限于隐藏&#xff0c;混淆&#xff0c;加密等操作&#xff0c;进一步保护软件的利益不受损坏&#xff0c;下面给…

TK养号工具开发会用上的源代码科普!

在当今数字化时代&#xff0c;社交媒体平台的崛起使得网络账号的维护与管理变得日益重要&#xff0c;其中&#xff0c;TK作为一款备受欢迎的社交媒体平台&#xff0c;吸引了大量用户。 在TK上进行账号养护&#xff0c;即通过各种方式提升账号权重、增加曝光量&#xff0c;已成…

光伏仿真系统不可忽视的功能:建模与仿真!

光伏仿真系统具备多种功能&#xff0c;能够支持对光伏发电系统进行深入研究和优化。为什么说建模与仿真功能是最不可忽视的呢&#xff1f;我们先来看看建模功能。 光伏仿真系统可以通过光伏插件或扩展程序&#xff0c;创建精确的光伏组件模型&#xff0c;包括光伏板、支架、逆变…

MyBatis入门程序详解

目录 一、MyBatis概述 二、编写MyBatis入门程序 三、配置SQL提示 四、传统jdbc的劣势 一、MyBatis概述 MyBatis是一个基于Java的持久层框架&#xff0c;它内部封装了JDBC操作&#xff0c;使得开发人员可以更专注于SQL语句本身而非繁琐的JDBC操作细节。在MyBatis中&#xff0…

软件测试面试1000问(含答案)

1、自动化代码中,用到了哪些设计模式? 单例设计模式工厂模式PO设计模式数据驱动模式面向接口编程设计模式 2、什么是断言( Assert) ? 断言Assert用于在代码中验证实际结果是不是符合预期结果&#xff0c;如果测试用例执行失败会抛出异常并提供断言日志 3、什么是web自动化…

AI工具集盘点!2024年必备的AI软件都在这,一文全部拿下!

AI工具哪款好&#xff0c;有哪些值得推荐&#xff1f; 不可否认&#xff0c;当下各式各样的AI工具层出不穷&#xff0c;面对不断涌现的AI工具&#xff0c;各位在选用时是否无从下手&#xff0c;或是抽不出时间&#xff0c;逐一体验对比不同AI工具的差异…… 这也是现如今许多…

基于单片机的防酒驾控制系统设计

摘 要&#xff1a; 酒后驾车的危害十分巨大&#xff0c;因此&#xff0c;笔者介绍了一种基于单片机的防酒驾控制系统。系统由酒精传感器 MQ-3测量汽车驾驶员体内的酒精含量浓度&#xff0c;通过 A/D 转换器转换成数字信号传给单片机&#xff0c;经过单片机处理后显示酒精浓度&a…

OpenEuler 22.03 LTS SP3 CVE-2024-6387 OpenSSH 漏洞修复指南

一、漏洞概括 漏洞名称OpenSSH Server远程代码执行漏洞漏洞编号CVE-2024-6387公开时间2024-7-1CVSS 3.1分数8.1威胁类型代码执行漏洞等级暂无技术细节状态已公开在野利用状态不明确PoC状态x86已公开EXP状态未公开 OpenSSH是SSH&#xff08;Secure Shell&#xff09;协议的开源…

通过shell脚本创建MySQl数据库

通过shell脚本创建数据库 #!/bin/bashserverIP10.1.1.196 SERVER_NAMEecho $serverIP | cut -d . -f4cat<<EOF>db.sql drop database if exists ${SERVER_NAME}_scheduler; drop database if exists ${SERVER_NAME}_kms; drop database if exists ${SERVER_NAME}_uim…

用NanoID换掉 UUID,好处是?【送源码】

当我们在分布式环境中存储一些数据的时候&#xff0c;不得不面对的一个选择&#xff0c;就是ID生成器。 使用一个唯一的字符串&#xff0c;来标识一条完整的记录。 这时候&#xff0c;不能使用md5或者sha1来对整个记录做摘要&#xff0c;因为我们后续还要改动这个记录。也不能…

科技云报道:人工智能“顶流”齐聚WAIC 2024,他们都做了什么?

科技云报道原创。 一个由智能驱动的未来世界长啥样&#xff1f; 从完成跨海跨城航线的“空中的士”、全无人驾驶汽车、实现奔跑功能的全尺寸通用人形机器人到百度文心一言、讯飞星火、阿里通义千问、华为盘古、商汤日日新等大模型&#xff0c;从智能制造引领的“灯塔工厂”到…

芯科普| 矽光子是什麼?可以用在哪些领域?点击查看!

随着生成式人工智能的崛起&#xff0c;数据传输需求亦呈现爆发式增长。而在此背景下&#xff0c;台积电在半导体展览上披露的硅光子&#xff08;SiPh&#xff1a;Silicon Photonics&#xff09;技术进展&#xff0c;更是将硅光子推向了风口浪尖&#xff0c;成为了市场的宠儿。 …

一拖二快充线:生活充电新风尚,高效便捷解决双设备充电难题

一拖二快充线在生活应用领域的优势与双接充电的便携性问题 在现代快节奏的生活中&#xff0c;电子设备已成为我们不可或缺的日常伴侣。无论是智能手机、平板电脑还是笔记本电脑&#xff0c;它们在我们的工作、学习和娱乐中扮演着至关重要的角色。然而&#xff0c;随着设备数量…

【ue5】虚幻5同时开多个项目

正常开ue5项目我是直接在桌面点击快捷方式进入 只会打开一个项目 如果再想打开一个项目需要进入epic 再点击启动就可以再开一个项目了