多架构下的 Docker 镜像

2023年 1月 4日 23.7k 0

1. 开启 Docker 的 experimental 特性

这里先开启 Docker 的 experimental 特性,方便下文使用相关命令。编辑文件 vim ~/.docker/config.json ,增加如下内容:

1
2
3
4
{
  "experimental": "enabled",
  "debug": true
}

注意,这里不是 /etc/docker/daemon.json 文件,也不需要重启 Docker 。

2. Docker 镜像

从 Docker 1.10 、 Registry 2.3 开始,Docker 引入了 manifest 用于描述镜像的元数据。

2.1 Dockerfile 如何转换成镜像

如上图,Dockerfile 中的每行命令,在构建镜像时都会关联一个 layer 。layer 是对镜像层的简单包装。这些镜像层在存储时,会得到复用,也就是说多个镜像使用到一个镜像层时,仅存储一份。这里面还有一些概念上的细节,可以暂时忽略。

2.2 Docker 与 Registry 如何传输镜像

镜像的元数据信息包括 size 、digest、layers 等信息。Docker 与 Registry 推拉镜像时,首先会传输 manifest 信息,仅当镜像层在当前环境中不存在时,才会进行网络传输,否则直接复用本地镜像层。

2.3 manifest 的文件结构

直接查看镜像的 manifest

  • 查看 manifest
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
docker manifest inspect jenkins/jnlp-slave

{
	"schemaVersion": 2,
	"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
	"config": {
		"mediaType": "application/vnd.docker.container.image.v1+json",
		"size": 12327,
		"digest": "sha256:9b5976169d3504ea796a4af75f8648db9a500e8b9351ee19276031108c59f429"
	},
	"layers": [
		{
			"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
			"size": 50382041,
			"digest": "sha256:f15005b0235fa8bd31cc6988c4f2758016fe412d696e81aecf73e52be079f19e"
		},
		{
			"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
			"size": 7812166,
			"digest": "sha256:41ebfd3d2fd0de99b1c63aa36a507bf5555481d06e571d84ed84440d30671494"
		},
		...
  ]
}
  • 查看多架构 manifest

通过 manifest.list 这个 mediaType ,可以将多个镜像整合为一个。在不同的 architecture 和 os 条件下,Docker 会自动拉取适配当前环境的镜像。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
docker manifest inspect maven

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 1579,
         "digest": "sha256:3c5d1c8795c96b775723cf912b297850feb1fc8f4b98ec2eda4303f3a6277310",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      }
   ]
}

3. 常见的几种多架构镜像的组织方式

不同的 OS 和 CPU 能运行的镜像会有差别。OS 层面,主要可以分为 Windows 和 类 Linux 的镜像。CPU 层面,主要有 amd64 、 arm 、ppc64le 、 s390x 等架构的镜像。amd64 也就是 x86-64 ,通常作为默认的架构,不用特意指明 amd64 和 linux 。

3.1 通过 namespace 区分不同架构

格式 namespaces-{ARCH}-{OS}/image:tag

  • amd64
1
shaowenchen-amd64/coredns:latest
1
shaowenchen-arm/coredns:latest

3.2 通过 image name 区分不同架构

格式 namespaces/image-{ARCH}-{OS}:tag

  • amd64
1
shaowenchen/coredns-amd64:latest
  • arm
1
shaowenchen/coredns-arm:latest

3.3 通过 tag name 区分不同架构

格式 namespaces/image:tag-{ARCH}-{OS}

  • amd64
1
shaowenchen/coredns:latest-amd64
  • arm
1
shaowenchen/coredns:latest-arm

4. manifest list 管理多架构镜像

manifest list 是一个镜像清单列表,用来存放不同架构的镜像信息。简单点说,就是新建了一个拉取镜像的入口,关联了不同架构的镜像,没有任何新的镜像层生成。

  • 首先推送镜像
1
2
3
docker push shaowenchen/coredns:coredns-amd64
docker push shaowenchen/coredns:coredns-arm
docker push shaowenchen/coredns:coredns-arm64

否则,下面的步骤会报错 no such manifest: docker.io/shaowenchen/coredns:coredns-amd64

  • 创建多架构的 manifest list
1
2
3
4
5
6
docker manifest create shaowenchen/coredns:latest 
    shaowenchen/coredns:coredns-amd64 
    shaowenchen/coredns:coredns-arm 
    shaowenchen/coredns:coredns-arm64 --amend

Created manifest list docker.io/shaowenchen/coredns:latest
  • [可选]更新相关架构的信息
1
docker manifest annotate shaowenchen/coredns:latest shaowenchen/coredns:coredns-arm --arch arm
  • 查看 manifest list
 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
26
27
28
29
30
31
32
33
34
35
docker manifest inspect shaowenchen/coredns:latest

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 739,
         "digest": "sha256:242d440e3192ffbcecd40e9536891f4d9be46a650363f3a004497c2070f96f5a",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 739,
         "digest": "sha256:e9e08bce9d74a48723518a476f67ada25d00ed69dd3719c3fde41b10d390b0d0",
         "platform": {
            "architecture": "arm",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 739,
         "digest": "sha256:969a21696cff473cb4d36854b15118885fd414394d09444cfd111213fabcd982",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      }
   ]
}
  • 推送到 DockerHub
1
2
3
docker manifest push shaowenchen/coredns:latest

sha256:bcdaff4935b922edd8f415323e04d3a77374f5ddabe0a59d649fd0b6be4ad5ef
  • 在 DockerHub 页面查看推送的镜像

在各种架构下,都可以使用同一条命令,拉取镜像:

1
docker pull shaowenchen/coredns:latest

这给部署带来了极大的便利,不需要给镜像拼接 architecture 和 os 信息。不同架构下,可以使用同一套部署程序。

5. 参考

  • https://docs.docker.com/engine/reference/commandline/manifest/

相关文章

KubeSphere 部署向量数据库 Milvus 实战指南
探索 Kubernetes 持久化存储之 Longhorn 初窥门径
征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
那些年在 Terraform 上吃到的糖和踩过的坑
无需 Kubernetes 测试 Kubernetes 网络实现
Kubernetes v1.31 中的移除和主要变更

发布评论