The multi architecture image creation guide has arrived, please check it!

Time:2022-5-8

Summary:Using multi architecture image allows docker to pull the corresponding image according to the system architecture. The deployment script of services can use the same configuration between systems with different architectures, reducing the service configuration and improving the consistency of services between different system architectures.

background

Because kubernetes cluster supports the system of AMD64 and arm64 architecture, both types of nodes may be scheduled by the cluster during container deployment; Therefore, when the container is packaged and pushed to the image warehouse, it needs to consider supporting multiple architectures to prevent the operation failure caused by scheduling to unsupported architecture nodes.

brief introduction

  • Docker register: v2. 3.0 supports multi architecture mirroring
  • Docker CLI
  • v1. 11. Support multi architecture image pulling
  • v18. 03 start to support multi architecture image production

reference material:

Production instructions

Although the multi architecture standard has existed for a long time, the official docker cli has been available until v18 The production of multi architecture image is supported only in version 03; Or you can consider using third-party tools. Refer to:Build docker image supported by multi CPU architecture

Docker v18 is used for subsequent multi architecture image production 09 version.

Set docker

Docker uses the manifest command to set manifest_ List thus supports multi architecture. To docker v18 Up to version 09, the manifest command is still experimental, so you need to configure docker to enable the experimental function.

Docker daemon

Modify the configuration file / etc / docker / daemon JSON, add configuration “experimental”: true:

$ sudo cat /etc/docker/daemon.json
[sudo] password for zhangsan:
{
    "data-root": "/home/common/docker",
    "Experimental": true, < - enables the experimental function of docker daemon
    "storage-driver": "overlay2",
    "log-driver": "json-file",
    "log-opts": {
        "max-file": "10",
        "max-size": "100m"
    },
    "insecure-registries": [
        "docker-hub.***.com"
    ]
}

Docker Cli

Modify the configuration file of the current user’s home directory ~ / docker/config. JSON, add configuration “experimental”: “enabled”:

$ cat ~/.docker/config.json
{
    "Experimental": "enabled", < - enables the experimental function of 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"
            }
        }
}

Verify configuration

Restart the docker service, run the docker manifest manually, and the following message appears, indicating that the configuration is successful:

$ 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.

Image packaging

The sample program stop is a go program. After starting, it pauses and does not do any operation. It is compiled to AMD64 and arm64 platforms, and runs on AMD64 platforms as follows:

$ 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

Use the same dockerfile:

$ cat Dockerfile
FROM scratch

COPY stop /stop
ENTRYPOINT ["/stop"]

AMD64 version

$ cd amd64

$ ls
Dockerfile  stop

#Tag platform information.
$ 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

#You can use the subcommand inspect of manifest to view the manifest information of the image. Since it is a private warehouse, you need to use the -- inspect parameter.
$ 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 version

$ 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

#Since the machine packaging the image is an AMD64 architecture, the architecture in the application image of arm64 is AMD64, which can be modified later or packaged directly on the arm64 machine.
$ 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"
                        }
                ]
        }
}

Verify mirroring

$ 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"

Create manifest_ LIST

Create a manifest_ List refers to the mirror image of the previous two different platforms.

$ 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"
                                }
                        ]
                }
        }
]

Modify manifest_ LIST

Modify the newly created manifest_ List to make the image correspond to the schema.

$ 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"
                                }
                        ]
                }
        }
]

Push manifest_ List to image warehouse

Created manifest_ List will be saved in the local directory ~ / Docker / manifests. When pushing, you can use the – P (- – purge) parameter to delete local data:

$ 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

verification

$ 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

#Select the image without architecture information from the system drop-down list of AMD64 architecture
$ 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

#Normal operation
$ docker run docker-hub.***.com/zhangsan/stop:1.0
^C%

#Select the image without architecture information from the system drop-down list of arm64 architecture
[[email protected] ~]# 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

[[email protected] ~]# docker images | grep stop

[[email protected] ~]# 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

[[email protected] ~]# docker images | grep stop
docker-hub.***.com/zhangsan/stop                          1.0                 1fc97e49b088        16 hours ago        666.5 kB

#Normal operation
[[email protected] ~]# docker run docker-hub.***.com/zhangsan/stop:1.0
^CShutting down, got signal: Interrupt

Upgrade manifest_ LIST

Post upgrade manifest_ The list method is similar to creating, such as docker hub. COM / Zhangsan / stop: 1.0-amd64 image upgrade or docker hub. COM / Zhangsan / stop: 1.0 this manifest_ To associate list with other images, you need to upgrade manifest_ LIST。 Points to note:

  • Use the parameter – A (- – amend) when creating manifest
  • If the upgrade is not associated with the desired image, you can manually delete the locally saved manifest and try again

Benefits of using multi architecture mirroring

Using multi architecture image allows docker to pull the corresponding image according to the system architecture. The deployment script of services can use the same configuration between systems with different architectures, reducing the service configuration and improving the consistency of services between different system architectures.

This article is shared from the Huawei cloud community “Ding! Put away this multi architecture image production guide”, the original author: thirteenmans.

Click follow to learn about Huawei’s new cloud technology for the first time~

Recommended Today

Explain type protection in typescript

catalogue summary Type Asserts In syntax Instanceof syntax Typeof syntax summary summary When using union types in typescript, you often encounter this embarrassing situation: interface Bird { //Unique method fly(); //Common method layEggs(); } interface Fish { //Unique method swim(); //Common method layEggs(); } function getSmallPet(): Fish | Bird { // … } let pet […]