Docker / 云原生

构建跨平台镜像:使用Docker Buildx

浅时光博客 · 11月18日 · 2023年 · 1.5w 次已读

一、场景描述


一次构建多处部署的镜像分发显著提高了应用的交付效率。对于需要在不同平台部署应用的情况,利用 docker buildx 构建跨平台的镜像是一种快捷高效的解决方案。

通常,常见做法是为每个平台单独构建一个版本。但当用于开发的平台与部署的目标平台不同时,实现这一目标并不容易。例如,在 x86 架构上开发一个应用程序,然后将其部署到 ARM 平台的机器上,通常需要准备 ARM 平台的基础设施用于开发和编译。

二、使用Buildx


默认的 docker build 命令无法实现跨平台构建任务,因此我们需要安装 buildx 插件来扩展其功能。Docker Buildx 提供了一种更灵活、高效且支持多平台构建的方法,适用于各种复杂的构建场景。它可以通过简单的命令行参数来扩展 Docker 构建的功能,使得容器镜像的构建变得更加便捷和高效。

在 Linux 环境中,QEMU 提供了一个称为用户态模式(User mode)的模拟模式。通过在 Linux 内核中注册一个二进制转换处理程序,QEMU 在程序运行时会动态地翻译目标架构的二进制文件,以便在当前系统的 CPU 架构上运行。这种模式的最终效果就是,我们可以在本地环境中仿真运行目标 CPU 架构的二进制文件。

借助 QEMU 的用户态模式,我们能够创建轻量级的虚拟机环境(如 chroot 或容器),在这个环境中进行编译工作,与在本地环境中进行编译没有本质区别,操作简单高效。事实上,这个特性也被广泛地应用于 Docker 镜像的跨平台构建。

通过利用用户态模式,我们能够在不同 CPU 架构之间灵活切换,为软件开发和部署提供了极大的便利性和灵活性原文链接:https://www.dqzboy.com。这种技术不仅在开发过程中有着广泛的应用,也是在容器技术中实现跨平台构建的重要基础。

2、Docker Buildx功能

多平台构建:

Buildx 允许你在单个命令中构建多个架构的容器镜像,从而支持在不同的 CPU 架构上运行。这对于跨平台开发和部署非常有用,特别是在混合架构的环境中。

构建缓存:

Buildx 支持本地和远程的构建缓存,可以显著加快构建过程。它可以缓存前一次构建的结果,避免重复下载和构建。

实验性功能:

Buildx 提供了对一些实验性功能的支持,比如使用 --platform 选项指定目标平台、使用 --build-arg BUILDKIT_INLINE_CACHE=1 开启内联缓存等。

并发构建:

Buildx 允许同时在多个节点上构建多个镜像,从而提高构建效率。

外部构建器:

通过与外部构建器(如 QEMU)结合使用,Buildx 可以支持在一个架构上构建另一个架构的镜像。

镜像导出:

Buildx 可以将构建的镜像导出为 tar 文件,方便在没有 Docker 环境的地方使用。

3、Docker Buildx使用

3.1:启用Docker Buildx

macOS 或 Windows 系统的 Docker Desktop,以及 Linux 发行版通过 deb 或者 rpm 包所安装的 docker 内置了 buildx,不需要另行安装。

  • 查看buildx是否可用
docker buildx version

如果你的 docker 没有 buildx 命令,可以下载二进制包进行安装:

  1. 首先从 Docker buildx 项目的 release 页面找到适合自己平台的二进制文件。
  2. 将下载的二进制文件下载到你的本地机器上,并确保文件名为 docker-buildx。
  3. 将 docker-buildx 二进制文件移动到 Docker 的插件目录 ~/.docker/cli-plugins。如果该目录不存在,可以先创建它。
mv docker-buildx ~/.docker/cli-plugins/
  1. 确保二进制文件具有执行权限。
chmod +x ~/.docker/cli-plugins/docker-buildx

4、启用 binfmt_misc

Docker for Linux 不支持构建 arm 架构镜像,我们可以运行一个新的容器让其支持该特性。如果你使用的是 Docker 桌面版(MacOS 和 Windows),默认已经启用了 binfmt_misc,可以跳过这一步。

注意:Linux 内核版本需要 4.x 以上,特别是 CentOS7 系统,默认是3.10

[root@DevOps ~]# docker run --rm --privileged tonistiigi/binfmt:latest --install all

# 验证是 binfmt_misc 否开启:
[root@DevOps ~]# ls -al /proc/sys/fs/binfmt_misc
  • 验证是否启用了相应的处理器
[root@DevOps ~]# cat /proc/sys/fs/binfmt_misc/qemu-arm
# 这表示 binfmt_misc 对象(在这里是 qemu-arm)是启用的
enabled
# 这是指定用于解释目标架构二进制文件的解释器。这里使用的是/usr/bin/qemu-arm
interpreter /usr/bin/qemu-arm
# 这是一组标志,它们指示了如何处理目标二进制文件。
flags: OCF
# 这个字段指示了在目标文件的哪个偏移量开始执行解释器。
offset 0
# 这个字段描述了目标文件的特征码,也就是一个标志序列,用于识别文件的格式。
magic 7f454c4601010100000000000000000002002800
# 这个字段定义了哪些部分是需要匹配的,哪些部分是通配符。
mask ffffffffffffff00fffffffffffffffffeffffff

5、切换多平台构建器

由于 Docker 默认的构建器实例不支持同时指定多个 --platform,因此我们需要首先手动创建一个新的构建器实例并进行相应的替换。

5.1:创建新的Buildx构建器

注意:如果你是私有仓库,并且是http没有证书的情况下创建构建器实例时,需要指定–driver-opt network=host 和 –config /etc/buildkit/buildkitd.toml 两个参数,而且需要在Docker的daemon.json中添加”insecure-registries”: [“私有仓库地址地址或者域名”]

  1. 创建 /etc/buildkit/buildkitd.toml 配置文件,并填写下面的配置内容
[root@DevOps ~]# vim /etc/buildkit/buildkitd.toml
debug = 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."私有仓库地址IP或者域名"]
  http = true
  insecure = true
  1. 创建一个名为 my-builder 的新构建器,并将其设置为当前活动构建器
[root@DevOps ~]# docker buildx create --name my-builder --use --driver-opt network=host --config /etc/buildkit/buildkitd.toml

上面指令介绍:

  • docker buildx create: 这是创建 Docker Buildx 构建器的命令。
  • --name my-builder: 这个选项用于指定构建器的名称,这里构建器被命名为 my-builder。
  • --use: 这个选项表示在创建后立即使用新创建的构建器。
  • --driver-opt network=host: 这是一个构建器驱动选项,它在构建器后台运行的时候将使用宿主机的网络命名空间。这样构建器就可以访问宿主机上的网络资源。
  • --config /etc/buildkit/buildkitd.toml: 这个选项用于指定构建器的配置文件路径。在这里,它指定了配置文件为 /etc/buildkit/buildkitd.toml

5.2:检查当前部署的构建器

[root@DevOps ~]# docker buildx inspect

5.3:启动新的Buildx构建器

[root@DevOps ~]# docker buildx inspect my-builder --bootstrap

5.4:检查当前使用的构建器

  • 查看当前使用的构建器及构建器支持的 CPU 架构
[root@DevOps ~]# docker buildx ls

三、构建多平台镜像


1、创建Dockerfile

  • 创建一个最简单的容器应用来进行操作说明
[root@DevOps ~]# vim Dockerfile
# 通过 --platform=$TARGETPLATFORM指定平台的Alpine 镜像作为基础
FROM --platform=$TARGETPLATFORM alpine

# 运行 uname 命令并将输出写入 os.txt 文件
RUN uname -a > /os.txt

# 设置容器启动时默认执行的命令
CMD cat /os.txt

2、构建镜像并推送

  • 推送之前,先登入私有镜像仓库
[root@DevOps ~]# docker login <私有镜像仓库>
Username: 用户
Password: 密码

Login Succeeded

执行构建,使用 – -push 参数推送到镜像仓库

[root@DevOps ~]#  docker buildx build --platform linux/arm64,linux/amd64 -t 私有仓库地址/public/REPOSITORY[:TAG] --push .

查看私有镜像仓库项目下是否有多个不通架构的镜像

3、测试多平台镜像

运行结束后可以通过 docker buildx imagetools 探查已推送到远程仓库的镜像:

[root@DevOps ~]# docker buildx imagetools inspect 私有仓库地址/public/REPOSITORY[:TAG]
构建跨平台镜像:使用 docker buildx

由于我们在本机已经启用了 binfmt_misc,现在可以在本地系统上运行任何 CPU 架构的 Docker 镜像了。这意味着我们可以在本地直接测试这些镜像,确保它们没有问题。

这里可以直接拉取不同CPU架构镜像的sha256 值拉取

[root@DevOps ~]# docker run -it --rm 私有仓库地址/public/demo:v1.0@sha256:xxx

本文作者:浅时光博客
原文链接:https://www.dqzboy.com/16083.html
版权声明:知识共享署名-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)协议进行许可,转载时请以>超链接形式标明文章原始出处和作者信息
免责声明:本站内容仅供个人学习与研究,严禁用于商业或非法目的。请在下载后24小时内删除相应内容。继续浏览或下载即表明您接受上述条件,任何后果由用户自行承担。

0 条回应

必须 注册 为本站用户, 登录 后才可以发表评论!