コンテナのメリットの一つとしてポータビリティ(可搬性)があります。
アプリケーションをコンテナイメージとしてパッケージングすることで、プラットフォームに依存せずに利用できるという特徴は、昨今のコンテナの普及に大きく貢献していると言えます。
しかしこのポータビリティは、プラットフォームのCPUアーキテクチャーが同一の場合にのみ成立するものであり、アーキテクチャーをまたぐことはできません。様々なアーキテクチャーのプラットフォームを組み合わせて管理していくマルチクラウド環境においては、これは避けては通れない課題です。
この課題に対するソリューションとして開発されているのが、Docker BuildxやBuildahといったマルチアーキテクチャー対応のイメージビルドツールになります。
本記事ではこれらのマルチアーキテクチャーイメージのビルド機能を検証しました。
#マルチアーキテクチャーイメージとは
単一のイメージの中に複数のアーキテクチャー形式を含めることができるものを指します。
https://matsuand.github.io/docs.docker.jp.onthefly/desktop/multi-arch/
Docker HubやQuay.ioにおける公式イメージの多くはマルチアーキテクチャーに対応しており、Pullする際に自動で実行環境に合わせたアーキテクチャーのイメージが提供されるため、ユーザーはアーキテクチャーを意識せずに利用することができます。
DockerコマンドのプラグインであるDocker Buildxや、コンテナイメージの操作に特化したツールであるBuildahを使うことで、マルチアーキテクチャーイメージをビルドすることができます。
Docker Buildxによるイメージビルド
ビルド環境としてIA MacにDocker Desktopを導入して使用します。
Docker BuildxはDocker Desktopに含まれています。
https://www.docker.com/products/docker-desktop
マルチアーキテクチャーイメージをビルドする
以下ステップでイメージをビルドします。
①マルチアーキテクチャーイメージビルド用のビルダーインスタンスを作成する
②そのインスタンスを使用してマルチアーキテクチャーイメージをビルドする
またマルチアーキテクチャーイメージのビルドには、マルチアーキテクチャーイメージに対応するレジストリにイメージを保管する必要があります。ここではDocker Hubを使用します。
### 事前に使用するイメージレジストリにログインしておく
### ビルダーインスタンスを作成・設定する
$ docker buildx create --name multibuilder
multibuilder
### ビルダーインスタンス確認
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
multibuilder docker-container
multibuilder0 unix:///var/run/docker.sock inactive
...
### 作成したビルダーインスタンスを使用する
$ docker buildx use multibuilder
### amd64とs390x(IBM Z)のマルチアーキテクチャーイメージをビルドする
$ cat Dockerfile
FROM nginx
COPY ./index.html /usr/share/nginx/html
$ cat ./index.html
multiarch image built on mac
$ chmod 644 index.html
### ビルド実行&Docker HubにPush
$ docker buildx build --platform linux/amd64,linux/s390x -t xxx/nginx-multiarch:mac --push .
[+] Building 23.5s (15/15) FINISHED
...
### Mac上での稼動確認
$ docker run --name nginx -d -p 8080:80 docker.io/xxx/nginx-multiarch:mac
$ curl http://localhost:8080
multiarch image built on mac
###ビルドしたイメージをIBM Zで実行
実行環境にはIBM CloudのHyper Protect Virtual Server(Ubuntu 20.04)です。
これにPodmanを導入して実行しています。
### IBM Z上からイメージをPullする
$ podman pull xxx/nginx-multiarch:mac
✔ docker.io/xxx/itlmc-nginx-multiarch:mac
...
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/xxx/nginx-multiarch mac 0fe47c2b2120 14 hours ago 137 MB
$ podman run --name nginx -d -p 8080:80 nginx-multiarch:mac
cca52fc38526e2ea0e7520702849ef5c082e3ef28450abd7e7c5300d5f2ceb9f
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cca52fc38526 docker.io/xxx/nginx-multiarch:mac nginx -g daemon o... 4 seconds ago Up 4 seconds ago 0.0.0.0:8080->80/tcp nginx
$ curl http://localhost:8080
multiarch image built on mac
#Buildahによるイメージビルド
ビルド環境はIBM CloudのHyper Protect Virtual Server(Ubuntu 20.04)です。
###マルチアーキテクチャーイメージをビルドする
Buildahの場合、
①それぞれのアーキテクチャーのイメージをビルドし、
②それらのイメージのインデックスとなるマニフェストを作成する
というステップです。
このマニフェストファイルをマルチアーキテクチャーイメージとして利用します。
イメージレジストリはDocker Hubを使用します。
### 事前に使用するイメージレジストリにログインしておく
$ cat Dockerfile
FROM nginx
COPY ./index.html /usr/share/nginx/html
$ cat index.html
multiarch image built on HPVS
$ chmod 644 index.html
### s390xイメージをビルドする
$ buildah bud --arch s390x -t docker.io/xxx/nginx-s390x:v1
...
Successfully tagged docker.io/xxx/nginx-s390x:v1
1e9bff381553835b9c8583c267e33bfc29c5874c2d878cdb2667da16fde2db2d
### amd64イメージをビルドする
$ buildah bud --arch amd64 -t docker.io/xxx/nginx-amd64:v1
...
Successfully tagged docker.io/xxx/nginx-amd64:v1
207da08ff0d56e125ffb4fcac0214dfd15387f7c511757959cb25af965a1a60c
$ buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/xxx/nginx-amd64 v1 207da08ff0d5 6 minutes ago 146 MB
docker.io/xxx/nginx-s390x v1 1e9bff381553 9 minutes ago 144 MB
docker.io/library/nginx latest f6987c8d6ed5 2 days ago 146 MB
### イメージのPush
$ podman push docker.io/xxx/nginx-amd64:v1
...
$ podman push docker.io/xxx/nginx-s390x:v1
...
### それぞれのアーキテクチャーのイメージを参照するマルチアーキテクチャーイメージ(マニフェスト)を作成する
$ buildah manifest create nginx-multiarch:hpvs
5510878c5973d3dcf8daf301acfe0f215675ce5daa41eb11f0a14ca242c4ee63
$ buildah manifest add --override-arch=amd64 --override-os=linux --os=linux --arch=amd64 nginx-multiarch:hpvs docker.io/xxx/nginx-amd64:v1
5510878c5973d3dcf8daf301acfe0f215675ce5daa41eb11f0a14ca242c4ee63: sha256:87f0a1bdc43d86b6531693834026b32c12b7d29096b3eea756d65d7b05ea6c29
$ buildah manifest add --override-arch=s390x --override-os=linux --os=linux --arch=s390x nginx-multiarch:hpvs docker.io/xxx/nginx-s390x:v1
5510878c5973d3dcf8daf301acfe0f215675ce5daa41eb11f0a14ca242c4ee63: sha256:4dd94a2bc2f38584148b291f5532faafe889e811668f6c4366bdd88b2adf9a0e
### マルチアーキテクチャーイメージをPush
$ buildah manifest push --all nginx-multiarch:hpvs docker://xxx/nginx-multiarch:hpvs
...
### ローカルのイメージを一旦削除
$ buildah rmi 5510878c5973 207da08ff0d5 1e9bff381553
untagged: localhost/nginx-multiarch:hpvs
untagged: docker.io/xxx/nginx-amd64:v1
untagged: docker.io/xxx/nginx-s390x:v1
$ buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest f6987c8d6ed5 2 days ago 146 MB
### 改めてマルチアーキテクチャーイメージをPull
$ buildah pull docker.io/rkyce/nginx-multiarch:hpvs
...
Writing manifest to image destination
Storing signatures
1e9bff381553835b9c8583c267e33bfc29c5874c2d878cdb2667da16fde2db2d
$ buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/xxx/nginx-multiarch hpvs 1e9bff381553 21 minutes ago 144 MB
docker.io/library/nginx latest f6987c8d6ed5 2 days ago 146 MB
### s390xのイメージがPullできていることを確認
$ podman inspect docker.io/xxx/nginx-multiarch:hpvs |grep s390x
"Architecture": "s390x",
### 正常に稼動することを確認
$ podman run --name nginx -d -p 8080:80 docker.io/xxx/nginx-multiarch:hpvs
ef3bce605bc6e0f675f8546bb74298d6ee940077768e032caa2f3bdcaa0d5df3
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef3bce605bc6 docker.io/xxx/nginx-multiarch:hpvs nginx -g daemon o... 7 seconds ago Up 8 seconds ago 0.0.0.0:8080->80/tcp nginx
$ curl http://localhost:8080
multiarch image built on HPVS
###ビルドしたイメージをMacで実行
実行環境はIA MacのDocker Desktopです。
### MacからマルチアーキテクチャーイメージをPull
$ docker pull xxx/nginx-multiarch:hpvs
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xxx/nginx-multiarch hpvs 207da08ff0d5 45 minutes ago 141MB
### amd64のイメージがPullできていることを確認
$ docker inspect xxx/nginx-multiarch:hpvs |grep Arch
"Architecture": "amd64",
### 正常に稼動することを確認
$ docker run --name nginx -d -p 8080:80 xxx/nginx-multiarch:hpvs
2f43abf7796cf4428f8e333d6a07b32b29a2545eecd78417659734a4a2b1a12a
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f43abf7796c xxx/nginx-multiarch:hpvs "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp nginx
$ curl http://localhost:8080
multiarch image built on HPVS
まとめ
Docker BuildxとBuildahでそれぞれマルチアーキテクチャーイメージのビルドができることを確認しました。
Docker Buildxは単一のリポジトリに複数のアーキテクチャーのイメージを包含できるのに対し、Buildahのマニフェストと実イメージが分かれる構成となっており、利便性に少し差がある印象です。
またDocker BuildxはDocker社の公式ドキュメントはじめ、Web上で参照できる情報が比較的充実していますが、Buildahはまだ情報が少なく、手探りの検証が必要になります。