docker构建跨平台应用(x86,arm)
1.直接从官方仓库拉去指定平台的镜像
1 | docker pull --platform=<plartform> <image-name>:<tag> |
例:
1 | docker pull --platform=arm64 nginx:latest |
2.打包指定平台的镜像
安装并使用 buildx
使用 builder
构建跨平台镜像
现在一些准备工作已经就绪,我们终于可以使用 builder
构建跨平台镜像了。
这里以一个 Go 程序为例,来演示如何构建跨平台镜像。
hello.go
程序如下:
这个程序非常简单,执行后打印 Hello, 操作系统/CPU 架构
。
Go 程序还需要一个 go.mod
文件:
编写 Dockerfile
内容如下:
这是一个普通的 Dockerfile
文件,为了减小镜像大小,使用了多阶段构建。它跟构建仅支持当前平台的镜像所使用的 Dockerfile
没什么两样。
以上三个文件需要放在同一个目录下,然后就可以在这个目录下使用 docker buildx
来构建跨平台镜像了。
docker buildx build
语法跟 docker build
一样,--platform
参数表示构建镜像的目标平台,-t
表示镜像的 Tag,.
表示上下文为当前目录。
唯一不同的是对 --platform
参数的支持,docker build
的 --platform
参数只支持传递一个平台信息,如 --platform linux/arm64
,也就是一次只能构建单个平台的镜像。
而使用 docker buildx build
构建镜像则支持同时传递多个平台信息,中间使用英文逗号分隔,这样就实现了只用一条命令便可以构建跨平台镜像的功能。
执行以上命令后,我们将会得到一条警告:
这条警告提示我们没有为 docker-container
驱动程序指定输出,生成结果将只会保留在构建缓存中,使用 --push
可以将镜像推送到 Docker Hub 远程仓库,使用 --load
可以将镜像保存在本地。
这是因为我们新创建的 mybuilder
是启动了一个容器来运行 BuildKit
,它并不能直接将构建好的跨平台镜像输出到本机或推送到远程,必须要用户来手动指定输出位置。
我们可以尝试指定 --load
将镜像保存的本地主机。
结果会得到一条错误日志。看来它并不支持直接将跨平台镜像输出到本机,这其实是因为传递了多个 --platform
的关系,如果 --platform
只传递了一个平台,则可以使用 --load
将构建好的镜像输出到本机。
那么我们就只能通过 --push
参数将跨平台镜像推送到远程仓库了。不过在此之前需要确保使用 docker login
完成登录。
现在登录 Docker Hub 就可以看见推送上来的跨平台镜像了。
我们也可以使用 imagetools
来检查跨平台镜像的 manifest
信息。
可以看到,这个跨平台镜像包含了两个目标平台的镜像,分别是 linux/arm64
和 linux/amd64
。
我们分别在 Apple M2 芯片平台和 Linux x86 平台来启动这个 Docker 镜像看下输出结果。
至此,我们使用 builder
完成了跨平台镜像的构建。
使用交叉编译
以上演示的构建跨平台镜像过程就是利用 QEMU 的能力,因为 Go 语言的交叉编译非常简单,所以我们再来演示一下如何使用交叉编译来构建跨平台镜像。
我们只需要对 Dockerfile
文件进行修改:
其中 BUILDPLATFORM
、TARGETOS
、TARGETARCH
、TARGETPLATFORM
四个变量是 BuildKit
提供的全局变量,分别表示构建镜像所在平台、操作系统、架构、构建镜像的目标平台。
在构建镜像时,BuildKit
会将当前所在平台信息传递给 Dockerfile
中的 BUILDPLATFORM
参数(如 linux/arm64
)。
通过 --platform
参数传递的 linux/arm64,linux/amd64
镜像目标平台列表会依次传递给 TARGETPLATFORM
变量。
而 TARGETOS
、TARGETARCH
两个变量在使用时则需要先通过 ARG
进行声明,BuildKit
会自动为其赋值。
在 Go 程序进行编译时,可以通过 GOOS
环境变量指定目标操作系统,通过 GOARCH
环境变量指定目标架构。
所以这个 Dockerfile
所表示的含义是:首先拉取当前构建镜像所在平台的 golang
镜像,然后使用交叉编译构建目标平台的 Go 程序,最后将构建好的 Go 程序复制到目标平台的 alpine
镜像。
最终我们会通过交叉编译得到一个跨平台镜像。
笔记:通过 FROM --platform=$BUILDPLATFORM image
可以拉取指定平台的镜像,由此我们可以知道,其实 golang 和 alpine 镜像都是支持跨平台的。
构建镜像命令不变:
启动镜像后输出结果不变:
至此,我们利用 Go 语言的交叉编译完成了跨平台镜像的构建。
平台相关的全局变量
关于上面提到的几个全局变量,BuildKit
后端预定义了一组 ARG 全局变量(共 8 个)可供使用,其定义和说明如下:
变量 | 说明 |
---|---|
TARGETPLATFORM | 构建镜像的目标平台,如:linux/amd64,linux/arm/v7,windows/amd64。 |
TARGETOS | TARGETPLATFORM 的操作系统,如:linux、windows。 |
TARGETARCH | TARGETPLATFORM 的架构类型,如:amd64、arm。 |
TARGETVARIANT | TARGETPLATFORM 的变体,如:v7。 |
BUILDPLATFORM | 执行构建所在的节点平台。 |
BUILDOS | BUILDPLATFORM 的操作系统。 |
BUILDARCH | BUILDPLATFORM 的架构类型。 |
BUILDVARIANT | BUILDPLATFORM 的变体。 |
使用示例如下:
删除 builder
我们已经实现了使用 builder
构建跨平台镜像。如果现在你想要恢复环境,删除新建的 builder
。则可以使用 docker buildx rm mybuilder
命令来完成。
跟随 mybuilder
启动的 buildx_buildkit_mybuilder0
容器也会随之被删除。
现在再使用 docker buildx ls
命令查看构建器列表,已经恢复成原来的样子了。
功能清单
除了前文介绍的几个 buildx
常用命令,更多功能可以通过 --help
参数进行查看。
如 stop
、rm
可以管理 builder
的生命周期。每条子命令又可以使用 docker buildx COMMAND --help
方式查看使用帮助,感兴趣的同学可以自行学习。
https://mioto.me/posts/offline-docker-buildx-and-registry-for-multi-platform-image-building/
__EOF__

本文链接:https://www.cnblogs.com/databank/p/17979533.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤