随着arm64架构的普及,越来越多的开发者使用arm64架构的服务器,但是x86_64架构的服务器仍然流行,那么在构建镜像过程中就需要支持多种架构的镜像。本文将介绍2种方式在 Docker
中构建多架构镜像。
manifest
手动创建manifest
文件,然后使用docker manifest push
命令推送到镜像仓库。比如社区中同时支持 arm64
和 amd64
架构的kube-rbac-proxy
镜像,现在希望推送到自建 harbor
镜像仓库。
Pull
社区镜像到本地
1
2
| docker pull quay.io/brancz/kube-rbac-proxy:v0.8.0-arm64
docker pull quay.io/brancz/kube-rbac-proxy:v0.8.0-amd64
|
创建 manifest
列表
1
| docker manifest create harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0 harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0-arm64 harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0-amd64
|
此时创建了一个 harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0
的 manifest
列表,其中包含了 arm64
和 amd64
两个架构的镜像。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| docker manifest inspect harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 739,
"digest": "sha256:34e8724e0f47e31eb2ec3279ac398b657db5f60f167426ee73138e2e84af6486",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 739,
"digest": "sha256:5a9f8e2f60fc4d02e364fa0192c01c79e8fac7e0c6a01cbc5b17152d6f21deae",
"platform": {
"architecture": "arm64",
"os": "linux"
}
}
]
}
|
设置 manifest
列表
1
2
| docker manifest annotate harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0 harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0-arm64 --os linux --arch arm64
docker manifest annotate harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0 harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0-amd64 --os linux --arch amd64
|
查看 manifest
列表
1
| docker manifest inspect harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0
|
推送 manifest
列表
1
| docker manifest push harbor.alongparty.cn/operator/kube-rbac-proxy:v0.8.0
|

buildx
在 Docker 19.03+
版本中可以使用 docker buildx build
命令使用 BuildKit
构建镜像。该命令支持 --platform
参数可以同时构建支持多种系统架构的 Docker
镜像,大大简化了构建步骤。
新建 builder
实例
1
2
3
4
5
6
| # 适用于国内环境
docker buildx create --use --name=mybuilder-cn --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master
docker buildx create --name mybuilder --driver docker-container
docker buildx use mybuilder
|
构建镜像
1
2
| FROM --platform=$TARGETPLATFORM busybox
COPY plugins /usr/share/elasticsearch/plugins
|
1
| docker buildx build --platform linux/arm64,linux/amd64 -t harbor.alongparty.cn/operator/es-plugins:7.13.4 --push .
|
注意: 在构建多架构镜像时底层镜像需要支持多架构,例如 busybox
镜像需要支持 linux/arm64
和 linux/amd64
两个架构。自身应用程序也需要支持多架构,比如 golang
编译的二进制文件需要支持 linux/arm64
和 linux/amd64
两个架构,不然在运行过程中可能会出现问题。
架构相关变量
Dockerfile 支持如下架构相关的变量
TARGETPLATFORM
构建镜像的目标平台,例如 linux/amd64, linux/arm/v7, windows/amd64。
TARGETOS
TARGETPLATFORM 的 OS 类型,例如 linux, windows
TARGETARCH
TARGETPLATFORM 的架构类型,例如 amd64, arm
TARGETVARIANT
TARGETPLATFORM 的变种,该变量可能为空,例如 v7
BUILDPLATFORM
构建镜像主机平台,例如 linux/amd64
BUILDOS
BUILDPLATFORM 的 OS 类型,例如 linux
BUILDARCH
BUILDPLATFORM 的架构类型,例如 amd64
BUILDVARIANT
BUILDPLATFORM 的变种,该变量可能为空,例如 v7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| #!/bin/bash
registry="harbor.alongparty.cn/default"
for image in $(cat images.txt)
do
docker pull $image
docker manifest inspect $image | jq -r '.manifests[]'| jq -r '[.digest,.platform.architecture,.platform.os] | @tsv' > manifests.txt
self_image=$(echo $image | awk -F/ -v OFS="-" '{print $(NF-1),$NF}')
while read line
do
manifest=$(echo "$line" | awk '{print $1}')
arch=$(echo $line | awk '{print $2}')
os=$(echo $line | awk '{print $3}')
if [[ $os == "linux" ]]; then
docker pull ${image}@${manifest}
docker tag ${image}@${manifest} ${registry}/${self_image}-${arch}
docker push ${registry}/${self_image}-${arch}
fi
done < manifests.txt
docker manifest create ${registry}/${self_image} ${registry}/${self_image}-amd64 ${registry}/${self_image}-arm64
docker manifest push ${registry}/${self_image}
done
|