本題に入る前にコンテナーイメージの話
DockerでもKubernetesでも、もちろんPodmanでも、コンテナプラットフォームではコンテナーイメージを利用します。 コンテナーイメージはDocker Hubのようなコンテナレジストリーからダウンロードして使います。
ベースイメージをカスタマイズする際は、作業用のマシンにDockerなどをインストールしてイメージのビルドを行うと思いますが、イメージを普通の方法でビルドした場合、同じCPUアーキテクチャーで利用できるコンテナイメージを作成できます。
しかし、最近は色々なCPUアーキテクチャーが一般に使われるようになりました。 例えばRaspberry Piは低価格ではありますが十分使えるARMボードの代表格です。 Apple Siliconを採用したMacを利用するユーザーも徐々に増えてきました。パブリッククラウドでもARM64アーキテクチャーのインスタンスを利用することもできるようになりつつあります。 ARM64アーキテクチャー向けのWindowsもWindows 11から正式版が提供されるようになり、徐々にARM64なWindows PCが増えるのではと期待されています。
というわけで、あなたが普段Intel CPUを使っている場合、コンテナーイメージを作成する場合に他のアーキテクチャーを想定しないと、他のCPUを実装するマシンでは実行できません。 さてそれだと他のアーキテクチャーを採用するマシンでは利用できません。それを解決するのがMulti-archイメージをビルドするという方法です。
Dockerの場合は次のような方法で、Multi-archイメージをビルドできます。
しかし、例えばIntel x86_64なCPUを実装するマシンで果たしてどうやって他のアーキテクチャーのイメージをビルドするのかと言うと、QEMUという仮想化技術を使っています。 今回はPodmanを使って、Multi-archイメージをビルドしてみようと思います。
イメージをビルドしてみる
まず、こんな内容のファイルを作成してみます。これはRed Hat UBI9イメージを使ってPython3でWeb Serverを実行するだけのイメージを生成するだけのものです。
FROM docker.io/redhat/ubi9:latest ENTRYPOINT ["python3", "-m","http.server","--bind","::"] EXPOSE 8000
ファイル名は慣習的にDockerfile
という名前で用意していたかと思います。
PodmanはDockerと高い互換性はありますが、でもDockerではありません。
Podmanの場合はContainerfileという名前でも自動で読み込んでくれます。他の名前のファイルを読み込む場合はDockerと同様に-f
オプションを付ければよいようです。
最近のPodmanではpodman buildx
というオプションが実装されています。使い勝手はdocker buildx
に近いですが、全く同じというわけではなくちょっと違うので注意が必要です。実行すると、プラットフォームで指定したアーキテクチャーのイメージを順番にビルドしてくれます。
% podman buildx build --platform linux/arm64,linux/amd64 . [linux/amd64] STEP 1/3: FROM docker.io/redhat/ubi9:latest [linux/amd64] STEP 2/3: ENTRYPOINT ["python3", "-m","http.server","--bind","::"] --> 2401eb60f4b [linux/amd64] STEP 3/3: EXPOSE 8000 [linux/amd64] COMMIT --> 3265d23466b [linux/arm64] STEP 1/3: FROM docker.io/redhat/ubi9:latest Trying to pull docker.io/redhat/ubi9:latest... [Warning] one or more build args were not consumed: [TARGETARCH TARGETOS TARGETPLATFORM] 3265d23466b185cacba10f12e6834b19c011d336189186da1b5634c0d71731c6 Getting image source signatures Copying blob sha256:a1d81c2404c27010bc762d7500fbf84cfb3724fca8e749f726ead9fa62158394 Copying blob sha256:8f38d96729f236ea7fd7c1073d21bb4135a49398db0eeff45301eb133278ed91 Copying config sha256:46308029455491e4bbaa7f3e5245b2e2f6fb6ddb411c5537823116a5dbc91095 Writing manifest to image destination Storing signatures [linux/arm64] STEP 2/3: ENTRYPOINT ["python3", "-m","http.server","--bind","::"] --> 9f91c9fabcf [linux/arm64] STEP 3/3: EXPOSE 8000 [linux/arm64] COMMIT --> 22850a8f470 [Warning] one or more build args were not consumed: [TARGETARCH TARGETOS TARGETPLATFORM] 22850a8f4709d01ae104e63e00efbcde609964ab2d303c79b563d9cf6af3ee15
イメージのビルドは従来のようにpodman image build
(もしくはpodman build
)を実行する方法もありますが、今回はpodman buildx build
を使う方法を中心に解説します。
$ platarch=linux/amd64,linux/arm64 $ podman image build --jobs=2 --platform=$platarch --manifest shazam .
ビルドしたイメージを確認してみる
できたイメージのイメージIDは、今回の場合は次になります。
[linux/arm64] COMMIT --> 22850a8f470 [linux/amd64] COMMIT --> 3265d23466b
イメージを確認してみます。名前無しのイメージが2つ追加されています(一番下のイメージはベースイメージです)。
% podman images REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 22850a8f4709 About a minute ago 249 MB <none> <none> 3265d23466b1 About a minute ago 231 MB docker.io/redhat/ubi9 latest 463080294554 7 days ago 249 MB
イメージIDをもとに、イメージのアーキテクチャーを確認してみます。
% podman image inspect 22850a8f4709 |grep Architecture "Architecture": "arm64", % podman image inspect 3265d23466b1 |grep Architecture "Architecture": "amd64",
ビルドしたイメージをDocker Hubに登録
あとはイメージをDocker Hubに登録すれば、共有できます。 Docker Hubの利用は初めての場合はアカウントを登録してください。Docker Pro以上のライセンスを持っている場合はそのアカウントでログインすればよいです。 その場合はFreeライセンスよりも制限が緩和されます。
Docker Hubのドメインはdocker.ioを指定すれば良いです。
まずはログインします。PodmanでDocker Hubにログインする場合はpodman login docker.io
と実行します。次にユーザー名とパスワードをそれぞれ入力しますが、Docker Hubのアカウントに2FAを設定している場合は、ユーザー名とAccess Tokensをそれぞれ入力します。
% podman login docker.io
イメージにタグを設定します。今回はDocker Hubにイメージを登録する想定なので、docker.io/your-username/image-name:tags
のような名前付けにします。
(例)
% podman image tag 22850a8f4709 docker.io/ytooyama/multiarch-example:latest-arm64 % podman image tag 3265d23466b1 docker.io/ytooyama/multiarch-example:latest-amd64
上記タグ付けしたイメージをリポジトリーに登録するには、つぎのように実行します。
% podman image push docker.io/ytooyama/multiarch-example:latest-arm64 && \ podman image push docker.io/ytooyama/multiarch-example:latest-amd64
ちなみに、Podman Desktopをインストールしている場合は、ログインやイメージのPushなどはPodman Desktopから実行できるので便利かもしれません。
これにより、Docker Hubのytooyama/multiarch-exampleに、2つのタグのイメージが登録されます。
イメージの利用
作成したイメージは他のコンテナプラットフォームでは次のように使えます。
amd64 (x86_64) マシンでは
$ podman container run -d -p 8000:8000 ytooyama/multiarch-example:latest-amd64
arm64/aarch64マシンでは
$ podman container run -d -p 8000:8000 ytooyama/multiarch-example:latest-arm64
Dockerで使う場合は、上記のpodmanコマンドをdockerに置き換えて実行するだけです。
KubernetesでPodを作成する場合は(但:ノードのアーキテクチャーに対応するイメージを利用すること)
apiVersion: v1 kind: Pod metadata: name: hello-multiarch spec: containers: - name: hello-multiarch image: ytooyama/multiarch-example:latest-amd64 ports: - containerPort: 8000 $ kubectl create -f pod.yaml
KubernetesでDeployment APIでPodを作成する場合は(但:ノードのアーキテクチャーに対応するイメージを利用すること)
apiVersion: apps/v1 kind: Deployment metadata: name: hello-multiarch spec: replicas: 2 selector: matchLabels: app: hello-multiarch template: metadata: labels: app: hello-multiarch spec: containers: - name: hello-multiarch image: ytooyama/multiarch-example:latest-amd64 ports: - containerPort: 8000 $ kubectl create -f deployment.yaml
あとはKubernetes Serviceを使えば、アクセスできるようになるはずです。
前回の記事のようにPodmanでDocker-composeコマンドを使ったアプリケーションの実行も普通にできるので、macOSでのローカルのコンテナ開発ではPodman + Podman Desktopでも良いのではなんて思い始めました。Podmanは他と比べて起動や処理が速くて気に入ってます。