最近,随着云服务器(Intel/AMD)和开发用个人PC(Apple Silicon等ARM)架构的碎片化,对不依赖于单一环境的多架构(Multi-Architecture)容器镜像的需求日益增长。本文将详细介绍如何在Mac环境下,仅使用Podman构建同时支持Intel(linux/amd64)和ARM(linux/arm64)架构的镜像。

1. 多架构镜像和清单(Manifest)的概念 🧠
通常,容器镜像遵循执行构建的主机架构。因此,在Apple Silicon Mac上简单构建的镜像无法在Intel服务器上运行。
多架构镜像使用“清单列表”(Manifest List)的概念。它充当目录,将多个架构的镜像捆绑在一个镜像标签下(例如:myapp:latest)。当用户拉取镜像时,容器引擎会检查当前系统的架构,并从清单中自动选择合适的镜像。
2. 准备工作:Mac环境下的Podman Machine设置 ⚙️
在Mac环境下,由于没有Linux内核,Podman无法原生运行,而是在虚拟机(VM)上运行。Mac上安装的Podman通过podman machine命令管理VM。
对于Apple Silicon(M1、M2、M3等)Mac,此VM内部默认支持通过QEMU或Apple的Rosetta 2进行x86_64(Intel)仿真。因此,无需像Linux环境那样安装复杂的仿真器软件包,只需运行VM即可。
# 初始化Podman虚拟机(仅首次)
podman machine init
# 运行Podman虚拟机
podman machine start
# 检查VM状态和仿真支持
podman info
3. 编写用于实践的Containerfile 📄
为了测试,我们将准备一个非常简单的镜像,它会输出架构信息。文件名可以是Containerfile或Dockerfile。
# Containerfile
FROM alpine:latest
# 输出构建环境架构的命令
CMD ["uname", "-m"]
4. 方法1:通过单个命令构建多架构镜像(推荐) 🚀
Podman提供了通过组合–platform和–manifest标志,一次性构建多个架构镜像并将其捆绑到清单中的功能。
# 同时构建linux/amd64和linux/arm64平台并创建my-multi-app:latest清单
podman build --platform linux/amd64,linux/arm64 --manifest my-multi-app:latest .
此命令的执行过程如下:
- 为amd64架构环境执行隔离的容器构建。(利用Mac的仿真功能)
- 为arm64架构环境执行隔离的容器构建。(Apple Silicon原生)
- 将两个独立的镜像保存到本地仓库。
- 创建一个名为my-multi-app:latest的清单列表,并将之前构建的两个镜像连接起来。
5. 方法2:单独构建后合并到清单 🧩
如果构建过程因架构而异,或者需要捆绑已构建的现有镜像,您可以手动控制清单。
# 1. 创建一个空清单
podman manifest create my-manual-app:latest
# 2. 按架构单独构建镜像
podman build --platform linux/amd64 -t my-manual-app:amd64 .
podman build --platform linux/arm64 -t my-manual-app:arm64 .
# 3. 将单独的镜像添加到已创建的清单中
podman manifest add my-manual-app:latest localhost/my-manual-app:amd64
podman manifest add my-manual-app:latest localhost/my-manual-app:arm64
6. 结果验证并推送到注册表 ☁️
检查生成的清单是否正确包含多个架构。
# 检查清单信息
podman manifest inspect my-multi-app:latest
检查输出JSON信息的manifests数组中是否同时存在amd64和arm64。确认无误后,推送到外部容器注册表(Docker Hub、AWS ECR等)。
# 将清单本身推送到注册表
# (与清单关联的所有架构的镜像层将一次性上传)
podman manifest push my-multi-app:latest docker://docker.io/myusername/my-multi-app:latest
清单推送完成后,无论是在Intel服务器还是ARM PC等任何设备上运行podman run –rm myusername/my-multi-app:latest,都会正确启动与该设备架构匹配的容器。
发表回复