在日常的开发中,我们会有让程序在不同平台运行的需求。除了常用的Windows系统,Linux系统以及Mac OS系统外,我们甚至还希望让程序运行在以树莓派为代表的ARM平台下,或者是跑在嵌入式设备的路由器上。要构建出适合不同平台的镜像并不是一件容易的事情,除非你直接到目标平台下构建,或者模拟出目标平台下的环境来进行构建。
最近我的开源项目GoDNS就有用户提了个issue,GoDNS的Docker镜像在树莓派平台下运行失败,从错误提示来看,就知道是镜像的问题。之前只考虑了镜像在Linux或者Mac OS下运行,完全没考虑兼容树莓派平台。解决的办法,最直接的就是在树莓派中去打包和构建镜像。不过,我手头又没有树莓派,难道要去买一个?这成本也有点太高了点。
幸好,新版的Docker从版本19.03后已经开始支持一个新的命令行工具,叫做buildx
,目地就是为了解决我们在一个平台下,一次性构建出多个平台可用镜像的需求。buildx
是一个基于命令行的Docker扩展插件。在MacOS下,如果你使用桌面版的Docker,非常容易启用这个插件,只需要打开Experimental features
这个选项即可。
启用这个新特性之后,需要重启Docker,然后在命令行进行验证:
1 | > docker buildx version |
看到显示的版本号,表示buildx已经启用成功。默认情况下,Docker不会启用多平台架构的构建器,需要我们自己创建一个新的构建器,并激活和启动这个新的构建器:
1 | > docker buildx create --name mybuilder |
创建完成后,启用新的构建器:
1 | > docker buildx inspect mybuilder --bootstrap |
最后,再次验证构建器是否正常运行:
1 | docker buildx ls |
在此可以看到,新的构建器已经支持其他多种平台。接下来,我们需要实战操作一下,用新的构建器,构建支持多系统平台的多个镜像。以我的项目GoDNS为例,Dockerfile如下:
1 | FROM golang:alpine AS builder |
Dockerfile使用多步构建并打包镜像。随后,我们使用docker buildx一次性构建出多CPU平台的镜像,并push到DockerHub:
1 | docker buildx build --platform linux/amd64,linux/386,linux/arm64,linux/arm/v7 -t timothyye/godns:latest . --push |
在DockerHub上,我们能看到同一个版本的镜像下,用digest区分出了基于不同平台版本的镜像:
而当不同系统的用户,通过docker pull命令去拉取镜像的时候,docker会自动pull跟当前系统所匹配的镜像。这样一来,我们再也不用为构建不同CPU架构的镜像而犯愁了。