原文链接:使用 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. CSS盒子模型+box-sizing

    当对文档进行布局时,浏览器渲染引擎会根据css-Box模型(CSS Basic Box model)将所有元素表示为一个矩形盒子.CSS决定这些盒子的大小,位置以及属性(颜色,背景,边框尺寸) 标准盒 ...

  2. Windows许可证即将过期怎么办?

    最近在使用电脑的时候,一开机就会弹窗出现:Windows 许可证即将过期.我勒个去,windows还会过期啊. 我搜遍全网,发现了一个很棒的 Windows10 永久激活的工具,而且没有广告什么乱七八 ...

  3. access技巧 access源码 这里都可找到哦

    这个网站不错,有很多access技巧 access源码 还有access公开课 access免费培训 access教程 大家要多看看哦: http://www.office-cn.net access ...

  4. python正则小结

    注意pattern字符串前要加r    原始字符串 元字符 .                匹配除换行的任意字符 ^            匹配开头 $            匹配结尾 表示重复   ...

  5. CSPS模拟 100

    我又挂分了T_T 这么吉利的数字..本来想考的好一点的 T1 没加当前弧优化(其实也不会),若志了 各种低错连篇而且没想到点不联通..没有奇度点就直接从1开始搜了 于是喜提70(犯了这两个若志错误应该 ...

  6. CSPS模拟99

    555我原型笔录 T1 不会线段树维护单调栈被dalao们踩爆 T2 我要实现这样一个东西: 已知a,b,c,使a=a-b,b=b-c 结果我把代码弄成这样: b=b-c;a=a-b; 然后就被dal ...

  7. go语言版本测试, 一段错误代码引发的血案

    起因: 最近在学习手写docker,看到了一段会编译错误的代码. 过程: 最近在学习docker,看到一段示例代码,每次编译时会报错. 因此, 无法继续下去, 只好在网上搜索解决方案, 用了很多时间, ...

  8. 通俗易懂了解React生命周期

    1.前言 学习React时,学习组件的生命周期是非常重要的,了解了组件的"从无到有再到无"所经历的各个状态,对日后写高性能的组件会有很大的帮助. 2.生命周期图 React的生命周 ...

  9. day2 上午 游戏 对应关系--->判断素数---->多重背包 神题

    #include<iostream> using namespace std; int n; ; ]; long long p[maxn]; long long dp[maxn][maxn ...

  10. 大数据之路day03--java循环的延申与练习(while 、do-while、for)

    在今天,我突然被一个很尴尬的问题问到了,问题是这样的:说一下java循环的应用场景. 我想很多人一下子听到这样的问题不知道怎么回答,大部分人会去想有什么循环格式,特点是什么.这些都是错误的,在往后的面 ...