原文链接:使用 buildx 构建多平台 Docker 镜像

在工作和生活中,我们可能经常需要将某个程序跑在不同的 CPU 架构上,比如让某些不可描述的软件运行在树莓派或嵌入式路由器设备上。特别是 Docker 席卷全球之后,我们可以轻松地在 ARM 设备上通过容器部署各种好玩的应用,而不用在意各种系统的差异性。

但是想要跨平台构建 Docker 镜像可不是一件轻松的活,要么到不同 CPU 架构的系统上全部构建一遍,要么就得在当前系统上通过虚拟化技术模拟不同的 CPU 架构,最后可能还要想办法合并镜像,费力不讨好。

不过值得庆幸的是,Docker 19.03 引入了一个新的实验性插件,该插件使得跨平台构建 Docker 镜像比以往更加容易了。在介绍这个新特性之前,我们先来了解一下跨 CPU 架构构建程序的基础知识。

1. 跨 CPU 架构编译程序的方法

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

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

如果你能够访问目标 CPU 架构的系统,并且该操作系统支持运行构建所需的各种工具,那么你可以直接在目标系统上编译程序。

以构建 Docker 镜像为例,你可以在树莓派上安装 Docker,然后在树莓派上通过 Dockerfile 直接构建 arm 平台的镜像。

如果无法访问目标 CPU 架构的系统该怎么办?有没有办法通过某种方式直接在当前系统上构建目标 CPU 架构的程序?请看下文...

方法二:模拟目标硬件

还记得我们小时候在各种网吧台球室之类的场合玩的街机游戏吗?放张图给你们回忆一下:

如果现在我们想重新体验以前玩过的街机游戏该怎么办?这时候就需要用到模拟器(Emulator)了。借助模拟器,我们可以让时光倒流,体验经典游戏的乐趣。

模拟器除了可以用来玩游戏之外,还可以用来跨 CPU 架构构建程序。最常用的模拟器是开源的 QEMU,QEMU 支持许多常见的 CPU 架构,包括 ARMPower-PCRISC-V 等。通过模拟一个完整的操作系统,可以创建通用的 ARM 虚拟机,该虚拟机可以引导 Linux,设置开发环境,也可以在虚拟机内编译程序。

然而,模拟整个操作系统还是有点浪费,因为在这种模式下,QEMU 将会模拟整个系统,包括计时器、内存控制器、总线控制器等硬件。但编译程序根本不需要关心这些,还可以再精简些。

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

在 Linux 上,QEMU 除了可以模拟完整的操作系统之外,还有另外一种模式叫用户态模式(User mod)。该模式下 QEMU 将通过 binfmt_misc 在 Linux 内核中注册一个二进制转换处理程序,并在程序运行时动态翻译二进制文件,根据需要将系统调用从目标 CPU 架构转换为当前系统的 CPU 架构。最终的效果看起来就像在本地运行目标 CPU 架构的二进制文件。

通过 QEMU 的用户态模式,我们可以创建轻量级的虚拟机(chroot 或容器),然后在虚拟机系统中编译程序,和本地编译一样简单轻松。后面我们就会看到,跨平台构建 Docker 镜像用的就是这个方法。

方法四:使用交叉编译器

最后介绍一种嵌入式系统社区常用的方法:交叉编译(cross-compilation)。

交叉编译器是专门为在给定的系统平台上运行而设计的编译器,但是可以编译出另一个系统平台的可执行文件。例如,amd64 架构的 Linux 系统上的 C++ 交叉编译器可以编译出运行在 aarch64(64-bit ARM) 架构的嵌入式设备上的可执行文件。再举个真实的例子,安卓设备的 APP 基本上都是通过这种方法来编译的。

从性能角度来看,该方法与方法一没什么区别,因为不需要模拟器的参与,几乎没有性能损耗。但交叉编译不具有通用性,它的复杂度取决于程序使用的语言,如果使用 Golang 的话,那就超级容易了。

在全民容器时代,我们讨论构建时不仅包括构建单个可执行文件,还包括构建容器镜像。而且构建容器镜像比上面说的方法更复杂,再加上 Docker 本身的复杂性,这几乎是一个老大难的问题。

但引入了新的实验性插件之后,构建多平台架构的 Docker 镜像就比以前容易多了,至于这个插件到底是啥,下文会详细介绍。

2. 构建多平台 Docker 镜像

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

下面就来演示一下如何在短短几分钟内使用 buildx 构建出不同平台的 Docker 镜像。步骤如下:

启用 buildx 插件

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

												

使用 buildx 构建多平台 Docker 镜像的更多相关文章

  1. Docker Buildx使用教程:使用Buildx构建多平台镜像

    写在前边 记录一下前阵子在X86_64平台使用Docker Buildx构建多平台镜像的办法,包含但不限于构建ARM镜像. 构建环境 软件名 版本 Ubuntu 18.04.2 LTS Docker ...

  2. 多阶段构建Golang程序Docker镜像

    Docker简介 Docker是基于Linux容器技术(LXC),使用Go语言实现的开源项目,诞生于2013年,遵循Apache2.0协议.Docker自开源后,受到广泛的关注和讨论. Docker在 ...

  3. 四:(之四)基于已有镜像构建自己的Docker镜像

    4构建自己的Docker镜像 4.1常用命令: 等同于docker commit 将一个被改变的容器创建成一个新的image 等同于docker build 通过Dockerfile创建一个image ...

  4. Jenkins教程(五)构建Java服务Docker镜像

    本文主旨 主要记录下如何使用Jenkins构建Java服务的Docker镜像,以及手动部署测试下 前期准备 已安装Jenkins 为jenkins用户添加到docker组内 本地装有maven,配置或 ...

  5. 使用Alipay代码源,构建自己的Docker镜像

    1. alipay 镜像仓库 地址 (自行换成自己的阿里镜像云DockerHub地址) https://cr.console.aliyun.com/repository/ 2.alipay 代码云 地 ...

  6. 如何构建自己的docker镜像

    需求情况:springboot项目想要部署到docker里面,如何部署? 步骤如下: 1.将jar包上传linux服务器 /usr/local/dockerapp 目录,在jar包所在目录创建名为 D ...

  7. 构建 Go 应用 docker 镜像的十八种姿势

    修炼背景 我夜以继日,加班加点开发了一个最简单的 Go Hello world 应用,虽然只是跑了打印一下就退出了,但是老板也要求我上线这个我能写出的唯一应用. 项目结构如下: . ├── go.mo ...

  8. 构建最小JDK Docker镜像

    参考: https://my.oschina.net/shyloveliyi/blog/1627020 1.首先下载jre,下载地址是https://www.java.com/en/download/ ...

  9. 使用dockerfile 构建springboot 的docker镜像

    1 新建一个 springboot 项目,并将其打包成 jar 文件.生成demo1.jar 文件 请参考 使用springBoot搭建REATFul风格的web demo 2 编写 dockerfi ...

随机推荐

  1. 配置IIS服务器提供APP文件下载

    [IIS7.IIS7.5] 1)打开IIS服务管理器,左边点到计算机(也可设置特定网站) 2)右边功能项中找到MIME类型,双击打开3)右键“添加”4)扩展名中填写".apk",M ...

  2. Unity修改脚本后调试

    修改脚本后调试有时候需要运行,为了提高效率可以设置编辑器中执行,同时也可以开启有效性检查(即更改面板变量即可刷新代码) [ExecuteInEditMode] public class XXXX: M ...

  3. Oauth 2.0学习

    OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为R ...

  4. egg-sequelize --- nodejs

    项目 egg + sequelize + mysql2 项目结构 配置 安装模块 npm install --save egg-sequelize npm install --save egg-cor ...

  5. mysql中的锁机制之悲观锁和乐观锁

    1.悲观锁? 悲观锁顾名思义就是很悲观,悲观锁认为数据随时就有可能会被外界进行修改,所以悲观锁一上来就会把数据给加上锁.悲观锁一般都是依靠关系型数据库提供的锁机制,然而事实上关系型数据库中的行锁,表锁 ...

  6. 小白学 Python(18):基础文件操作

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  7. csps模拟测试50反思

    又考崩了,T1一眼秒掉错误思路,然后迅速码完,并码完错误暴力,对拍拍上,以为AC.T2想到了二维莫队,发现是子任务就没去打,一直在想别的,T3最后想到60分打法,没有打完,也没时间暴力,挂掉.T2还有 ...

  8. SpringBoot 源码解析 (一)----- SpringBoot核心原理入门

    Spring Boot 概述 Build Anything with Spring Boot:Spring Boot is the starting point for building all Sp ...

  9. Jmeter与压测相关概念

    相关概念 RT(response time) 什么是RT? RT就是指系统在接收到请求和做出相应这段时间跨度 但是值得一提的是RT的值越高,并不真的就能说明我们的系统的吞吐量就很高, 比如说,如果存在 ...

  10. Linux命令实战(二)

    1.printf格式化输出(format and print data) 语法:printf(选项)(参数) 参数 输出格式:指定数据输出时的格式: 输出字符串:指定要输出的数据. 格式替代符 %c ...