LoginSignup
0
0

Docker multi-platform images

Posted at

はじめに

docker imageのmulti-platform buildの動作確認手順を記載したもの。

実施環境

  • Ubuntu 24.04, x86_64
  • Docker 26.1.0

Docker Private Registry構築

docker imageの格納先となるPrivate Registryを構築する。
構築後、イメージが格納できることを確認しておく。

コマンド
$ docker run -d --name docker-registry -p 5000:5000 registry
$ docker pull busybox:latest
$ docker tag busybox:latest localhost:5000/busybox:latest
$ docker push  localhost:5000/busybox:latest
実行結果のログ
実行結果
ubuntu@ubuntu:~/docker$ docker run -d --name docker-registry -p 5000:5000 registry
Unable to find image 'registry:latest' locally
latest: Pulling from library/registry
619be1103602: Pull complete
862815ae87dc: Pull complete
74e12953df95: Pull complete
6f0ce73649a0: Pull complete
ef4f267ce8ed: Pull complete
Digest: sha256:4fac7a8257b1d7a86599043fcc181dfbdf9c8f57e337db763ac94b0e67c6cfb5
Status: Downloaded newer image for registry:latest
14ee0d4b73c3e29eeb791630d14bd2ac249744c1dde48d42b52b71f6cbab084a
ubuntu@ubuntu:~/docker$ docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS
                        NAMES
14ee0d4b73c3   registry   "/entrypoint.sh /etc…"   4 seconds ago   Up 3 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   docker-registry
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ curl -k http://localhost:5000/v2/_catalog
{"repositories":[]}
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ docker pull busybox:latest
latest: Pulling from library/busybox
ec562eabd705: Pull complete
Digest: sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
ubuntu@ubuntu:~/docker$ docker tag busybox:latest localhost:5000/busybox:latest
ubuntu@ubuntu:~/docker$ docker images
REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
registry                 latest    d6b2c32a0f14   7 months ago    25.4MB
busybox                  latest    65ad0d468eb1   12 months ago   4.26MB
localhost:5000/busybox   latest    65ad0d468eb1   12 months ago   4.26MB
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ docker push  localhost:5000/busybox:latest
The push refers to repository [localhost:5000/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ curl -k http://localhost:5000/v2/_catalog
{"repositories":["busybox"]}
ubuntu@ubuntu:~/docker$

Builder instanceの作成

コマンド
$ docker run --privileged --rm tonistiigi/binfmt --install all
$ docker buildx create --name mybuilder --bootstrap --use --driver docker-container --driver-opt network=host
$ docker buildx ls
$ docker buildx inspect mybuilder
実行結果のログ
実行結果
ubuntu@ubuntu:~/docker$ docker run --privileged --rm tonistiigi/binfmt --install all
Unable to find image 'tonistiigi/binfmt:latest' locally
latest: Pulling from tonistiigi/binfmt
8d4d64c318a5: Pull complete
e9c608ddc3cb: Pull complete
Digest: sha256:66e11bea77a5ea9d6f0fe79b57cd2b189b5d15b93a2bdb925be22949232e4e55
Status: Downloaded newer image for tonistiigi/binfmt:latest
installing: riscv64 OK
installing: mips64le OK
installing: mips64 OK
installing: s390x OK
installing: ppc64le OK
installing: arm64 OK
installing: arm OK
{
  "supported": [
    "linux/amd64",
    "linux/arm64",
    "linux/riscv64",
    "linux/ppc64le",
    "linux/s390x",
    "linux/386",
    "linux/mips64le",
    "linux/mips64",
    "linux/arm/v7",
    "linux/arm/v6"
  ],
  "emulators": [
    "qemu-aarch64",
    "qemu-arm",
    "qemu-mips64",
    "qemu-mips64el",
    "qemu-ppc64le",
    "qemu-riscv64",
    "qemu-s390x"
  ]
}
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ docker buildx create --name mybuilder --bootstrap --use --driver docker-container --driver-opt network=host
[+] Building 14.8s (1/1) FINISHED
 => [internal] booting buildkit                                                                                                                                                      14.8s
 => => pulling image moby/buildkit:buildx-stable-1                                                                                                                                   13.5s
 => => creating container buildx_buildkit_mybuilder0                                                                                                                                  1.3s
mybuilder
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ docker buildx ls
NAME/NODE        DRIVER/ENDPOINT                   STATUS    BUILDKIT   PLATFORMS
mybuilder*       docker-container
 \_ mybuilder0    \_ unix:///var/run/docker.sock   running   v0.13.2    linux/amd64, linux/amd64/v2, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default          docker
 \_ default       \_ default                       running   v0.13.1    linux/amd64, linux/amd64/v2, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ docker buildx inspect mybuilder
Name:          mybuilder
Driver:        docker-container
Last Activity: 2024-05-19 14:35:08 +0000 UTC

Nodes:
Name:                  mybuilder0
Endpoint:              unix:///var/run/docker.sock
Driver Options:        network="host"
Status:                running
BuildKit daemon flags: --allow-insecure-entitlement=network.host
BuildKit version:      v0.13.2
Platforms:             linux/amd64, linux/amd64/v2, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
Labels:
 org.mobyproject.buildkit.worker.executor:         oci
 org.mobyproject.buildkit.worker.hostname:         ubuntu
 org.mobyproject.buildkit.worker.network:          host
 org.mobyproject.buildkit.worker.oci.process-mode: sandbox
 org.mobyproject.buildkit.worker.selinux.enabled:  false
 org.mobyproject.buildkit.worker.snapshotter:      overlayfs
GC Policy rule#0:
 All:           false
 Filters:       type==source.local,type==exec.cachemount,type==source.git.checkout
 Keep Duration: 48h0m0s
 Keep Bytes:    488.3MiB
GC Policy rule#1:
 All:           false
 Keep Duration: 1440h0m0s
 Keep Bytes:    4.657GiB
GC Policy rule#2:
 All:        false
 Keep Bytes: 4.657GiB
GC Policy rule#3:
 All:        true
 Keep Bytes: 4.657GiB
ubuntu@ubuntu:~/docker$

multi-platform buildを行うための要件があり、QEMUのインストールにtonistiigi/binfmtを使用した。

Strategies

You can build multi-platform images using three different strategies, depending on your use case:

  1. Using emulation, via QEMU support in the Linux kernel
  2. Building on a single builder backed by multiple nodes of different architectures.
  3. Using a stage in your Dockerfile to cross-compile to different architectures

Build&push

--platformオプションを使用して、x86/arm用のイメージ作成を行う。

コマンド
$ vi Dockerfile
$ docker buildx build --platform linux/amd64,linux/arm64 -t localhost:5000/test:latest --push .
実行結果のログ
実行結果
ubuntu@ubuntu:~/docker$ docker buildx build --platform linux/amd64,linux/arm64 -t localhost:5000/test:latest --push .
[+] Building 23.3s (15/15) FINISHED                                                                                                                             docker-container:mybuilder
 => [internal] load build definition from Dockerfile                                                                                                                                  0.2s
 => => transferring dockerfile: 278B                                                                                                                                                  0.0s
 => resolve image config for docker-image://docker.io/docker/dockerfile:1                                                                                                             2.4s
 => docker-image://docker.io/docker/dockerfile:1@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e                                                              1.5s
 => => resolve docker.io/docker/dockerfile:1@sha256:a57df69d0ea827fb7266491f2813635de6f17269be881f696fbfdf2d83dda33e                                                                  0.0s
 => => sha256:96918c57e42509b97f10c074d80672ecdbd3bb7dcd38c1bd95960cf291207416 11.98MB / 11.98MB                                                                                      0.6s
 => => extracting sha256:96918c57e42509b97f10c074d80672ecdbd3bb7dcd38c1bd95960cf291207416                                                                                             0.8s
 => [linux/amd64 internal] load metadata for docker.io/library/golang:alpine                                                                                                          2.7s
 => [linux/amd64 internal] load metadata for docker.io/library/alpine:latest                                                                                                          2.5s
 => [linux/arm64 internal] load metadata for docker.io/library/alpine:latest                                                                                                          2.7s
 => [internal] load .dockerignore                                                                                                                                                     0.1s
 => => transferring context: 2B                                                                                                                                                       0.0s
 => [linux/amd64 build 1/2] FROM docker.io/library/golang:alpine@sha256:f1fe698725f6ed14eb944dc587591f134632ed47fc0732ec27c7642adbe90618                                             13.1s
 => => resolve docker.io/library/golang:alpine@sha256:f1fe698725f6ed14eb944dc587591f134632ed47fc0732ec27c7642adbe90618                                                                0.1s
 => => sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1 32B / 32B                                                                                              0.4s
 => => sha256:db27d6512129ba324acd616fd920202156dfadb8ccae8ffd1ec862bd46277c98 126B / 126B                                                                                            0.4s
 => => sha256:3e347f261431f4a9affbd78ee6f59a7486c17be94c7c8274be137aab626f0555 69.34MB / 69.34MB                                                                                      2.5s
 => => sha256:667a4259027594465efe0982aec566a89095e879511d0716b4ae322f291e393d 292.90kB / 292.90kB                                                                                    0.6s
 => => extracting sha256:667a4259027594465efe0982aec566a89095e879511d0716b4ae322f291e393d                                                                                             0.2s
 => => extracting sha256:3e347f261431f4a9affbd78ee6f59a7486c17be94c7c8274be137aab626f0555                                                                                             9.9s
 => => extracting sha256:db27d6512129ba324acd616fd920202156dfadb8ccae8ffd1ec862bd46277c98                                                                                             0.0s
 => => extracting sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1                                                                                             0.0s
 => [linux/arm64 stage-1 1/2] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                            1.6s
 => => resolve docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                                                0.1s
 => => sha256:bca4290a96390d7a6fc6f2f9929370d06f8dfcacba591c76e3d5c5044e7f420c 3.35MB / 3.35MB                                                                                        0.5s
 => => extracting sha256:bca4290a96390d7a6fc6f2f9929370d06f8dfcacba591c76e3d5c5044e7f420c                                                                                             0.8s
 => [linux/amd64 stage-1 1/2] FROM docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                            1.5s
 => => resolve docker.io/library/alpine:latest@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b                                                                0.1s
 => => sha256:4abcf20661432fb2d719aaf90656f55c287f8ca915dc1c92ec14ff61e67fbaf8 3.41MB / 3.41MB                                                                                        0.4s
 => => extracting sha256:4abcf20661432fb2d719aaf90656f55c287f8ca915dc1c92ec14ff61e67fbaf8                                                                                             0.8s
 => [linux/amd64 build 2/2] RUN echo "I am running on linux/amd64, building for linux/amd64" > /log                                                                                   0.8s
 => [linux/amd64->arm64 build 2/2] RUN echo "I am running on linux/amd64, building for linux/arm64" > /log                                                                            0.8s
 => [linux/amd64 stage-1 2/2] COPY --from=build /log /log                                                                                                                             0.2s
 => [linux/arm64 stage-1 2/2] COPY --from=build /log /log                                                                                                                             0.2s
 => exporting to image                                                                                                                                                                1.1s
 => => exporting layers                                                                                                                                                               0.3s
 => => exporting manifest sha256:aac2940ff03955e14222c5d6c0952829a21786fa635db7e472a17df2458c1fc5                                                                                     0.0s
 => => exporting config sha256:7d93dd4b642c38e2c06eb16dc4706963642fe9804e7bf643e71ea637824d7a69                                                                                       0.0s
 => => exporting attestation manifest sha256:475ca97131d0c82289cf017101e45fc857a7d99ea2e75cda3fb9bba727fefc8b                                                                         0.0s
 => => exporting manifest sha256:ecb899a3e0ff4527a8ca5cd5e0429ae522b9ebb35d0ce60ee7a2c8a1819ac987                                                                                     0.0s
 => => exporting config sha256:7ecdf7f0056dd4a8bf6d5e8c24bb6005171e0bda11ad01bd5170531f9f38c6c4                                                                                       0.0s
 => => exporting attestation manifest sha256:cc24a5d4575484fb6635d9fbd9973181169d23f601bd31cc12baa4773cba9e71                                                                         0.0s
 => => exporting manifest list sha256:f6be49b394a70df268599d736cb67b257fb9b54ca332d67eb4694b22e6871ca1                                                                                0.0s
 => => pushing layers                                                                                                                                                                 0.3s
 => => pushing manifest for localhost:5000/test:latest@sha256:f6be49b394a70df268599d736cb67b257fb9b54ca332d67eb4694b22e6871ca1                                                        0.2s
ubuntu@ubuntu:~/docker$

Dockerfileは、下記に記載されているCross compile用のサンプルをそのまま使用した。

動作確認

作成したイメージをそれぞれ起動し指定されたアーキテクチャーのイメージになっているか確認する。
docker run実行時に--platformオプションを指定してx86/armのイメージを起動する。

コマンド
$ docker run --rm --platform linux/amd64 localhost:5000/test:latest uname -m
$ docker run --rm --platform linux/arm64 localhost:5000/test:latest uname -m
実行結果のログ
実行結果
ubuntu@ubuntu:~/docker$ docker run --rm --platform linux/amd64 localhost:5000/test:latest uname -m
Unable to find image 'localhost:5000/test:latest' locally
latest: Pulling from test
4abcf2066143: Already exists
a31561bca027: Pull complete
Digest: sha256:f6be49b394a70df268599d736cb67b257fb9b54ca332d67eb4694b22e6871ca1
Status: Downloaded newer image for localhost:5000/test:latest
x86_64
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$
ubuntu@ubuntu:~/docker$ docker run --rm --platform linux/arm64 localhost:5000/test:latest uname -m
Unable to find image 'localhost:5000/test:latest' locally
latest: Pulling from test
bca4290a9639: Pull complete
d1eef5f67990: Pull complete
Digest: sha256:f6be49b394a70df268599d736cb67b257fb9b54ca332d67eb4694b22e6871ca1
Status: Downloaded newer image for localhost:5000/test:latest
aarch64
ubuntu@ubuntu:~/docker$

Cleanup

使用したリソースを削除する。

コマンド
$ docker rm -f docker-registry
$ docker run --privileged --rm tonistiigi/binfmt --uninstall "qemu-*"
$ docker system prune -a
$ docker system prune --volumes -f
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0