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.0K
drwxrwxr-x 2 zhangsan zhangsan 4.0K Jun  3 17:21 amd64
drwxrwxr-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/stop
zsh: exec format error: arm64/stop

使用相同的Dockerfile:

$ cat Dockerfile
FROM scratch

COPY stop /stop
ENTRYPOINT ["/stop"]

amd64版本

$ cd amd64

$ ls
Dockerfile  stop

# 使用tag標注平台信息。
$ docker build -t docker-hub.***.com/zhangsan/stop:1.0-amd64 .
Sending build context to Docker daemon  242.7kB
Step 1/3 : FROM scratch
 --->
Step 2/3 : COPY stop /stop
 ---> ffb0d366bb8c
Step 3/3 : ENTRYPOINT ["/stop"]
 ---> Running in 715d1fbcf450
Removing intermediate container 715d1fbcf450
 ---> 0584fe60ca3d
Successfully built 0584fe60ca3d
Successfully tagged docker-hub.***.com/zhangsan/stop:1.0-amd64

$ docker images | grep stop
REPOSITORY                                        TAG                 IMAGE ID            CREATED             SIZE
docker-hub.***.com/zhangsan/stop        1.0-amd64           0584fe60ca3d        3 seconds ago       240kB

$ docker push docker-hub.***.com/zhangsan/stop:1.0-amd64
The push refers to repository [docker-hub.***.com/zhangsan/stop]
9e352dcc98ab: Pushed
1.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

$ ls
Dockerfile  stop

$ docker build -t docker-hub.***.com/zhangsan/stop:1.0-arm64 .
Sending build context to Docker daemon  669.2kB
Step 1/3 : FROM scratch
 --->
Step 2/3 : COPY stop /stop
 ---> e02dd9cc9ffa
Step 3/3 : ENTRYPOINT ["/stop"]
 ---> Running in 9b574680691a
Removing intermediate container 9b574680691a
 ---> 1fc97e49b088
Successfully built 1fc97e49b088
Successfully tagged docker-hub.***.com/zhangsan/stop:1.0-arm64

$ docker images | grep stop
docker-hub.***.com/zhangsan/stop        1.0-arm64           1fc97e49b088        8 seconds ago       666kB
docker-hub.***.com/zhangsan/stop        1.0-amd64           0584fe60ca3d        3 minutes ago       240kB

$ docker push docker-hub.***.com/zhangsan/stop:1.0-arm64
The push refers to repository [docker-hub.***.com/zhangsan/stop]
a0c07ccfc4ae: Pushed
1.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 stop
docker-hub.***.com/zhangsan/stop        1.0-arm64           1fc97e49b088        21 hours ago        666kB
docker-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-arm64
standard_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.0
no 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-arm64
Created 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 4
drwxr-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 stop
docker-hub.***.com/zhangsan/stop        1.0-arm64           1fc97e49b088        16 hours ago        666kB
docker-hub.***.com/zhangsan/stop        1.0-amd64           0584fe60ca3d        16 hours ago        240kB

# 在amd64架構的系統下拉取不帶架構信息的鏡像
$ uname -a
Linux 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.0
1.0: Pulling from zhangsan/stop
Digest: sha256:401767ef0864a65578bef86e3baed2e1e0be905d08d88b57cdeb299850400ece
Status: Downloaded newer image for docker-hub.***.com/zhangsan/stop:1.0

$ docker images | grep stop
docker-hub.***.com/zhangsan/stop        1.0-arm64           1fc97e49b088        16 hours ago        666kB
docker-hub.***.com/zhangsan/stop        1.0                 0584fe60ca3d        16 hours ago        240kB
docker-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 -a
Linux 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.0
1.0: Pulling from zhangsan/stop
439780881737: Pull complete
Digest: sha256:401767ef0864a65578bef86e3baed2e1e0be905d08d88b57cdeb299850400ece
Status: Downloaded newer image for docker-hub.***.com/zhangsan/stop:1.0

[root@kwephicprc09532 ~]# docker images | grep stop
docker-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 。

 

點擊關注,第一時間了解華為雲新鮮技術~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM