现在使用容器化技术来部署服务已成为主流, 而容器化技术的主流技术就是Docker了,就算是K8S,也主要是使用的Docker来构建镜像.
过往服务器主要都是amd64为主,但随着服务器领域ARM架构的崛起,加上国内信创环境也主要是ARM架构. 因此构建的容器镜像支持arm架构也慢慢成为一种普遍的需求.
于是,过往我们使用sudo docker build -t name:latest .
这样构建出来的镜像就不满足需求了,因为它构建出来的镜像只是你当前系统架构的特定版本.
想要构建多平台的镜像,有两种方式可以考虑:
- 在不同的架构系统上分别构建自己的镜像并上传 (不同名称的镜像名不能一样,否则会覆盖)
- 基于Docker提供的buildx工具,在任意架构平台的系统上,一次性构建并上传多平台镜像
第一种就不说了,因为它并不方便,也不实用,而且也麻烦. 今天的这篇文章主要就是介绍如何基于Docker提供的buildx工具,来构建多平台镜像,让你只做一次,满足不同平台.
事实上,只要你稍微关注Docker Hub,就会发现基本上主流的镜像,都是支持多架构的.
如上图所示, JDK的Docker同一个镜像支持非常多不同的平台.
一)
我们从常规的方式说起,基于Docker构建镜像的常规方式:
- 定义一个Dockerfile
# syntax=docker/dockerfile:1
#构建镜像
FROM eclipse-temurin:17.0.5_8-jre
WORKDIR /app
COPY ./myddd-starter-bootstrap-1.0.0-SNAPSHOT-fat.jar ./app
CMD ["java","-jar","/app/myddd-starter-bootstrap-1.0.0-SNAPSHOT-fat.jar","-Dfile.encoding=UTF-8"]
- 使用docker build构建一个镜像
sudo docker build -t lingen/myddd-starter:latest .
- 推送镜像
sudo docker push lingen/myddd-starter
相信有自己构建镜像操作的,都比较熟悉这个过程了.
这个推送到远程仓库的镜像如同我在前文中所述,它只是特定架构的,如果你在arm64架构系统上操作,它就是arm64架构. 如果是amd64,就是amd64架构.
这与我们的预期不符,我们希望无论是在arm64或是amd64架构上,都能使用同一镜像,如同docker hub中的大多数主流镜像一样
所幸,Docker早已识别到此需求,提供了buildx工具,这个就可以实现我们的上述目标
二)
接下来,我用buildx来重新构建上面这个镜像
- 检查buildx是否安装
如果你安装的是最新docker版本,buildx工具已经是内置的了. 识别你当前安装的环境是否支持buildx工具的方式是执行如下命令
sudo docker buildx help
如果见到如下输出
Usage: docker buildx [OPTIONS] COMMAND
Extended build capabilities with BuildKit
表明当前环境是支持buildx工具的,否则你需要升级docker以支持buildx
- 安装qemu-user-static与binfmt-support
之所以能在特定架构系统上构建不同的架构平台的镜像,就是使用的qemu虚拟技术. 所以,需要安装与之相关的这两个工具
在debian/ubuntu系统平台上,执行以下命令
sudo apt install -y qemu-user-static binfmt-support
需要注意的是,qemu-user-static需要linux内核4.8以上,binfmt-support需要2.1.7版本及以上.不过如果你使用的不是非常旧的Linux系统,基本不用担心这些限制
安装完成后,通过buildx的ls命令来检查支持了哪些不同架构平台
sudo docker buildx ls
# 输出如下
default * docker
default default running 20.10.22 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386
可以看到,当前的buildx支持上述这些架构平台,基本上这些已经足够了.
我基本只支持linux/arm64, linux/amd64这两个架构平台,它们是绝对的主流
- 切换使用
docker-container
驱动
buildx是一个包含很多功能的扩展工具包,支持多平台构建只是其中一个功能点.
而buildx默认使用的是docker
驱动,这个是不支持多平台构建的.所以我们需要切换使用docker-container
驱动,这个驱动是特别支持多平台构建的
如果你用docker
驱动来构建多平台镜像,会得到以下错误
ERROR: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")
所以,我们切换使用docker-container
驱动
# --name 名称任意命令,不影响
sudo docker buildx create --name=container --driver=docker-container --use --bootstrap
- 构建多平台架构镜像
好了,完成上述步骤后,现在你可以开始构建多平台架构镜像了
sudo docker buildx build --platform linux/amd64,linux/arm64 -t lingen/myddd-starter:latest .
--platform linux/amd64,linux/arm64
,我们指定构建linux/amd64与linux/arm64两个架构下的镜像
如果一切正常,你就可以看到构建多平台的日志输出
- 上传镜像
不过需要注意的是, 上述命令没有任何效果,成功构建后,你并不会在docker images中看到你构建的镜像,也不知道下一步该如何把这个多平台镜像上传到指定的镜像仓库中.
所以,你需要使用 --push把构建的多架构镜像直接上传到仓库.
因此,完整的命令是:
sudo docker buildx build --platform linux/amd64,linux/arm64 -t lingen/myddd-starter:latest . --push
这样,多架构镜像会直接构建并上传到指定的仓库
三)
虽然还有其它方式来实现这个目标,但当前使用buildx来构建多架构镜像是最简单的一种方式.
不过仍然有几点需要在最后说明补充一下:
docker desktop支持buildx
由于个人电脑操作系统基本不是Linux,而是Windows与MacOS. 所以需要补充说明, 在这两个系统上安装的Docker Desktop都支持buildx
不过,我个人不推荐使用Docker Desktop来实现这个, 还是建议在Windows下使用WSL,而在MacOS下使用multipass等工具来实现更妥当与合适
Dockerfile要支持多平台
想要支持多平台架构的,光有buildx并不充分与足够,你的Dockerfile本身要支持多平台,所谓的支持包括但不限于:
- 基础镜像本身要有对应平台的镜像
- RUN等命令中涉及到的命令,本身要在不同架构上是支持的,比如安装一些软件,本身这个安装操作在对应架构上是可以的,这是前提
还有其它一些类似的,你也基本能够理解了,基于builx构建多平台构建的前提是Dockefile本身要支持
你可以在任意平台上执行此操作
不管是amd64还是arm64,都支持构建多平台镜像.只要支持qemu相关的虚拟技术就行.
四)
下一次,在构建你自己的镜像时,你应该使用的是buildx而不是build了.