Multi-Architecture 镜像制作指南已到,请查收!
摘要:使用Multi-Architecture镜像,可以让docker根据系统架构去拉取对应的镜像,服务的部署脚本等可以在不同架构的系统间使用相同的配置,减化服务配置,提高了服务在不同系统架构间的一致性。
背景
由于Kubernetes集群支持amd64和arm64架构的系统,容器部署时两种类型的节点都可能被集群调度到;所以容器在打包推送到镜像仓库时需要考虑支持多架构,防止调度到不支持的架构节点导致运行失败。
简介
Docker register: v2.3.0开始支持Multi-Architecture镜像
Docker CLI
v1.11开始支持Multi-Architecture镜像拉取
v18.03开始支持Multi-Architecture镜像制作
参考资料:
Manifest标准:https://docs.docker.com/registry/spec/manifest-v2-1/
Manifest命令:https://docs.docker.com/engine/reference/commandline/manifest/
Registry:https://github.com/docker/distribution/releases/tag/v2.3.0
制作说明
虽然Multi-Architecture标准很早就有,但是官方的Docker CLI直到v18.03版本才开始支持Multi-Architecture镜像的制作;或者可以考虑使用第三方工具,参考:构建多CPU架构支持的Docker镜像
后续Multi-Architecture镜像的制作使用Docker v18.09版本进行说明。
设置Docker
Docker使用manifest命令来设置MANIFEST_LIST从而支持Multi-Architecture。到Docker v18.09版本为止,manifest命令还是实验性的,所以要配置Docker使能实验性功能。
Docker daemon
修改配置文件/etc/docker/daemon.json,添加配置"experimental": true:
$ sudo cat /etc/docker/daemon.json[sudo] password for zhangsan:{ "data-root": "/home/common/docker", "experimental": true, <- 使能docker daemon实验性功能 "storage-driver": "overlay2", "log-driver": "json-file", "log-opts": { "max-file": "10", "max-size": "100m" }, "insecure-registries": [ "docker-hub.***.com" ]}
Docker Cli
修改当前用户home目录的配置文件~/.docker/config.json,添加配置"experimental": "enabled":
$ cat ~/.docker/config.json{ "experimental": "enabled", <- 使能docker cli实验性功能 "proxies": { "default": { "httpProxy": "http://127.0.0.1:3128", "httpsProxy": "http://127.0.0.1:3128", "ftpProxy": "http://127.0.0.1:3128" } }}
验证配置
重启docker服务,手工运行docker manifest,出现如下信息说明配置成功:
$ docker manifest Usage: docker manifest COMMAND Manage Docker image manifests and manifest lists Commands: annotate Add additional information to a local image manifest create Create a local manifest list for annotating and pushing to a registry inspect Display an image manifest, or manifest list push Push a manifest list to a repository Run 'docker manifest COMMAND --help' for more information on a command.
镜像打包
示例程序stop是一个go程序,启动后暂停不做任何操作,编译到amd64和arm64平台,在amd64平台分别运行如下:
$ ll -hR.:total 8.0Kdrwxrwxr-x 2 zhangsan zhangsan 4.0K Jun 3 17:21 amd64drwxrwxr-x 2 zhangsan zhangsan 4.0K Jun 3 17:21 arm64 ./amd64:total 240K-rw-rw-r-- 1 zhangsan zhangsan 51 Jun 3 17:21 Dockerfile-rwxrwxr-x 1 zhangsan zhangsan 235K Jul 19 2014 stop./arm64:total 656K-rw-rw-r-- 1 zhangsan zhangsan 51 Jun 3 17:21 Dockerfile-rwxr-xr-x 1 zhangsan zhangsan 651K May 22 14:38 stop$ amd64/stop^C%$ arm64/stopzsh: exec format error: arm64/stop
使用相同的Dockerfile:
$ cat DockerfileFROM scratchCOPY stop /stopENTRYPOINT ["/stop"]
amd64版本
$ cd amd64$ lsDockerfile stop# 使用tag标注平台信息。$ docker build -t docker-hub.***.com/zhangsan/stop:1.0-amd64 .Sending build context to Docker daemon 242.7kBStep 1/3 : FROM scratch --->Step 2/3 : COPY stop /stop ---> ffb0d366bb8cStep 3/3 : ENTRYPOINT ["/stop"] ---> Running in 715d1fbcf450Removing intermediate container 715d1fbcf450 ---> 0584fe60ca3dSuccessfully built 0584fe60ca3dSuccessfully tagged docker-hub.***.com/zhangsan/stop:1.0-amd64$ docker images | grep stopREPOSITORY TAG IMAGE ID CREATED SIZEdocker-hub.***.com/zhangsan/stop 1.0-amd64 0584fe60ca3d 3 seconds ago 240kB$ docker push docker-hub.***.com/zhangsan/stop:1.0-amd64The push refers to repository [docker-hub.***.com/zhangsan/stop]9e352dcc98ab: Pushed1.0-amd64: digest: sha256:e5b6263b7e45840f139f1bf40b774294712c95df1b43d41598b736f07110341f size: 526# 可以用manifest的子命令inspect查看镜像的manifest信息,由于是私有仓库,需要使用--insecure参数。$ docker manifest inspect -v --insecure docker-hub.***.com/zhangsan/stop:1.0-amd64{ "Ref": "docker-hub.***.com/zhangsan/stop:1.0-amd64", "Descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "digest": "sha256:e5b6263b7e45840f139f1bf40b774294712c95df1b43d41598b736f07110341f", "size": 526, "platform": { "architecture": "amd64", "os": "linux" } }, "SchemaV2Manifest": { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1489, "digest": "sha256:0584fe60ca3dbff4c746d376855e89b72b022a4198373b3c8d4c41b97b8b4faf" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 71322, "digest": "sha256:7797d3b3ba41f7abc6a914250f793cf2d69a3e7c0bcc787a596eab4836554552" } ] }}
arm64版本
$ cd arm64$ lsDockerfile stop$ docker build -t docker-hub.***.com/zhangsan/stop:1.0-arm64 .Sending build context to Docker daemon 669.2kBStep 1/3 : FROM scratch --->Step 2/3 : COPY stop /stop ---> e02dd9cc9ffaStep 3/3 : ENTRYPOINT ["/stop"] ---> Running in 9b574680691aRemoving intermediate container 9b574680691a ---> 1fc97e49b088Successfully built 1fc97e49b088Successfully tagged docker-hub.***.com/zhangsan/stop:1.0-arm64$ docker images | grep stopdocker-hub.***.com/zhangsan/stop 1.0-arm64 1fc97e49b088 8 seconds ago 666kBdocker-hub.***.com/zhangsan/stop 1.0-amd64 0584fe60ca3d 3 minutes ago 240kB$ docker push docker-hub.***.com/zhangsan/stop:1.0-arm64The push refers to repository [docker-hub.***.com/zhangsan/stop]a0c07ccfc4ae: Pushed1.0-arm64: digest: sha256:089798dc96fcc3d2bf4da3ec4243adcc2507d2ae0c5ba77c5582af626702b3d6 size: 527# 由于打包镜像的机器是amd64架构,所以arm64的应用镜像中architecture为amd64,后面可以修改,或者直接在arm64机器上打包。$ docker manifest inspect -v --insecure docker-hub.***.com/zhangsan/stop:1.0-arm64{ "Ref": "docker-hub.***.com/zhangsan/stop:1.0-arm64", "Descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "digest": "sha256:089798dc96fcc3d2bf4da3ec4243adcc2507d2ae0c5ba77c5582af626702b3d6", "size": 527, "platform": { "architecture": "amd64", "os": "linux" } }, "SchemaV2Manifest": { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1488, "digest": "sha256:1fc97e49b0883f59e1e894404785ea1867b9e557d55bdac92f2da09c92b659e7" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 318698, "digest": "sha256:4397808817371da0348eb097ca181996165a9836d629aa1fb97b0d3824ffe2e2" } ] }}
验证镜像
$ docker images | grep stopdocker-hub.***.com/zhangsan/stop 1.0-arm64 1fc97e49b088 21 hours ago 666kBdocker-hub.***.com/zhangsan/stop 1.0-amd64 0584fe60ca3d 21 hours ago 240kB$ docker run docker-hub.***.com/zhangsan/stop:1.0-amd64^C%$ docker run docker-hub.***.com/zhangsan/stop:1.0-arm64standard_init_linux.go:207: exec user process caused "exec format error"
创建MANIFEST_LIST
创建一个MANIFEST_LIST引用之前两个不同平台的镜像。
$ docker manifest inspect -v --insecure docker-hub.***.com/zhangsan/stop:1.0no such manifest: docker-hub.***.com/zhangsan/stop:1.0$ docker manifest create --insecure docker-hub.***.com/zhangsan/stop:1.0 docker-hub.***.com/zhangsan/stop:1.0-amd64 docker-hub.***.com/zhangsan/stop:1.0-arm64Created manifest list docker-hub.***.com/zhangsan/stop:1.0$ docker manifest inspect -v --insecure docker-hub.***.com/zhangsan/stop:1.0[ { "Ref": "docker-hub.***.com/zhangsan/stop:1.0-amd64", "Descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "digest": "sha256:e5b6263b7e45840f139f1bf40b774294712c95df1b43d41598b736f07110341f", "size": 526, "platform": { "architecture": "amd64", "os": "linux" } }, "SchemaV2Manifest": { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1489, "digest": "sha256:0584fe60ca3dbff4c746d376855e89b72b022a4198373b3c8d4c41b97b8b4faf" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 71322, "digest": "sha256:7797d3b3ba41f7abc6a914250f793cf2d69a3e7c0bcc787a596eab4836554552" } ] } }, { "Ref": "docker-hub.***.com/zhangsan/stop:1.0-arm64", "Descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "digest": "sha256:089798dc96fcc3d2bf4da3ec4243adcc2507d2ae0c5ba77c5582af626702b3d6", "size": 527, "platform": { "architecture": "amd64", "os": "linux" } }, "SchemaV2Manifest": { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1488, "digest": "sha256:1fc97e49b0883f59e1e894404785ea1867b9e557d55bdac92f2da09c92b659e7" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 318698, "digest": "sha256:4397808817371da0348eb097ca181996165a9836d629aa1fb97b0d3824ffe2e2" } ] } }]
修改MANIFEST_LIST
修改刚创建的MANIFEST_LIST,使镜像和架构对应。
$ docker manifest annotate docker-hub.***.com/zhangsan/stop:1.0 docker-hub.***.com/zhangsan/stop:1.0-arm64 --arch arm64[ { "Ref": "docker-hub.***.com/zhangsan/stop:1.0-amd64", "Descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "digest": "sha256:e5b6263b7e45840f139f1bf40b774294712c95df1b43d41598b736f07110341f", "size": 526, "platform": { "architecture": "amd64", "os": "linux" } }, "SchemaV2Manifest": { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1489, "digest": "sha256:0584fe60ca3dbff4c746d376855e89b72b022a4198373b3c8d4c41b97b8b4faf" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 71322, "digest": "sha256:7797d3b3ba41f7abc6a914250f793cf2d69a3e7c0bcc787a596eab4836554552" } ] } }, { "Ref": "docker-hub.***.com/zhangsan/stop:1.0-arm64", "Descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "digest": "sha256:089798dc96fcc3d2bf4da3ec4243adcc2507d2ae0c5ba77c5582af626702b3d6", "size": 527, "platform": { "architecture": "arm64", "os": "linux" } }, "SchemaV2Manifest": { "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "config": { "mediaType": "application/vnd.docker.container.image.v1+json", "size": 1488, "digest": "sha256:1fc97e49b0883f59e1e894404785ea1867b9e557d55bdac92f2da09c92b659e7" }, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": 318698, "digest": "sha256:4397808817371da0348eb097ca181996165a9836d629aa1fb97b0d3824ffe2e2" } ] } }]
推送MANIFEST_LIST到镜像仓库
创建的MANIFEST_LIST会保存在本地目录~/.docker/manifests,在push时可以使用-p(--purge)参数删除本地数据:
$ ll -R ~/.docker/manifests/home/zhangsan/.docker/manifests:total 4drwxr-xr-x 2 zhangsan zhangsan 4096 Jun 3 17:57 docker-hub.***.com_zhangsan_stop-1.0/home/zhangsan/.docker/manifests/docker-hub.***.com_zhangsan_stop-1.0:total 8-rw-r--r-- 1 zhangsan zhangsan 733 Jun 3 17:57 docker-hub.***.com_zhangsan_stop-1.0-amd64-rw-r--r-- 1 zhangsan zhangsan 734 Jun 3 18:01 docker-hub.***.com_zhangsan_stop-1.0-arm64$ sudo docker manifest push -p --insecure docker-hub.***.com/zhangsan/stop:1.0[sudo] password for zhangsan:sha256:401767ef0864a65578bef86e3baed2e1e0be905d08d88b57cdeb299850400ece
验证
$ docker images | grep stopdocker-hub.***.com/zhangsan/stop 1.0-arm64 1fc97e49b088 16 hours ago 666kBdocker-hub.***.com/zhangsan/stop 1.0-amd64 0584fe60ca3d 16 hours ago 240kB# 在amd64架构的系统下拉取不带架构信息的镜像$ uname -aLinux SZX1000514415 4.4.0-87-generic #110-Ubuntu SMP Tue Jul 18 12:55:35 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux$ docker pull docker-hub.***.com/zhangsan/stop:1.01.0: Pulling from zhangsan/stopDigest: sha256:401767ef0864a65578bef86e3baed2e1e0be905d08d88b57cdeb299850400eceStatus: Downloaded newer image for docker-hub.***.com/zhangsan/stop:1.0$ docker images | grep stopdocker-hub.***.com/zhangsan/stop 1.0-arm64 1fc97e49b088 16 hours ago 666kBdocker-hub.***.com/zhangsan/stop 1.0 0584fe60ca3d 16 hours ago 240kBdocker-hub.***.com/zhangsan/stop 1.0-amd64 0584fe60ca3d 16 hours ago 240kB# 可正常运行$ docker run docker-hub.***.com/zhangsan/stop:1.0^C%# 在arm64架构的系统下拉取不带架构信息的镜像[root@kwephicprc09532 ~]# uname -aLinux kwephicprc09532 4.1.44-06.160.vhulk1711.1.1.aarch64 #1 SMP Tue Oct 16 18:45:06 UTC 2018 aarch64 aarch64 aarch64 GNU/Linux[root@kwephicprc09532 ~]# docker images | grep stop[root@kwephicprc09532 ~]# docker pull docker-hub.***.com/zhangsan/stop:1.01.0: Pulling from zhangsan/stop439780881737: Pull completeDigest: sha256:401767ef0864a65578bef86e3baed2e1e0be905d08d88b57cdeb299850400eceStatus: Downloaded newer image for docker-hub.***.com/zhangsan/stop:1.0[root@kwephicprc09532 ~]# docker images | grep stopdocker-hub.***.com/zhangsan/stop 1.0 1fc97e49b088 16 hours ago 666.5 kB# 可正常运行[root@kwephicprc09532 ~]# docker run docker-hub.***.com/zhangsan/stop:1.0^CShutting down, got signal: Interrupt
升级MANIFEST_LIST
后期升级MANIFEST_LIST方法与创建类似,如:docker-hub.***.com/zhangsan/stop:1.0-amd64镜像升级或docker-hub.***.com/zhangsan/stop:1.0这个MANIFEST_LIST要关联其它镜像时,都需要升级MANIFEST_LIST。需要注意几点:
manifest create时使用参数-a(--amend)
升级后没有关联到期望的镜像可以先手工删除本地保存的manifest再尝试
使用Multi-Architecture镜像的好处
使用Multi-Architecture镜像,可以让docker根据系统架构去拉取对应的镜像,服务的部署脚本等可以在不同架构的系统间使用相同的配置,减化服务配置,提高了服务在不同系统架构间的一致性。
本文分享自华为云社区《叮!快收好这份Multi-Architecture镜像制作指南》,原文作者:Thirteenmans 。
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/1916f2180c0e3c15d7f456ebe】。文章转载请联系作者。
华为云开发者社区
提供全面深入的云计算技术干货 2020.07.14 加入
华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/
评论