原文链接:使用 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. 【IntelliJ IDEA】Unable to save settings: Failed to save settings. Please restart IntelliJ IDEA 解决办法

    笔者打开IntelliJ IDEA敲代码的时候遇到了如下问题: IDEA Event Log窗口提示 Unable to save settings: Failed to save settings. ...

  2. 完美解决移动端H5页面的滑动穿透问题

    同事的分享,记录下来. 代码如下: css: body.modal-open { position: fixed; width: 100%; } js: // 兼容低版本 document.scrol ...

  3. 为什么磁盘慢会导致Linux负载飙升?

    一.CPU利用率和负载率的区别 这里要区别CPU负载和CPU利用率,它们是不同的两个概念,但它们的信息可以在同一个top命令中进行显示.CPU利用率显示的是程序在运行期间实时占用的CPU百分比,这是对 ...

  4. 学习笔记26_MVC前台强类型参数

    *一般在MVC中,aspx后台要往前台传递参数,使用ViewData["Key"] = obj; 前台就要 <%=(ViewData["key"] as ...

  5. 爬虫之selenium爬取京东商品信息

    import json import time from selenium import webdriver """ 发送请求 1.1生成driver对象 2.1窗口最大 ...

  6. [考试反思]0803NOIP模拟测试12:偿还

    嗯,rank5.没什么可评价的,高不算高低不算低. 一套好题,被我浪费了. 离上面280的大神差的有点远. 分机房的绝响就要来临. 越来越感觉自己变菜了,整体的能力水平在下滑. 说的不只是考试,包括平 ...

  7. JS- 封装、继承、多态

    http://www.cnblogs.com/silence516/articles/1509456.html

  8. PHP 精典面试题(附答案)

    1.输出Mozilla/4.0(compatible;MISIE5.01;Window NT 5.0)是,可能输出的语句是? A:$_SERVER['HTTP_USER_AGENT_TYPE']; B ...

  9. DAY 3 数论专场

    2019-07-23 今天的题目一个比一个神仙,很早之前就在讨论今天是不是晚上回宾馆就没脑子了,后来发现,是中午.... 一上午就讲了一个PPT,然而标题就两个子---数论... 这谁顶的住....整 ...

  10. JavaScript入门经典(第7版)读书笔记

    断断续续看了十来天,终于看完了,还是学到些东西,这本书还是不错的,各方面都有涉及. 补充了下之前不完善的JS 知识 笔记一般只记必要的东西.‎ Table of Contents 1. JavaScr ...