マルチ CPU アーキテクチャー対応の活用
読む時間の目安: 2 分
Docker イメージはマルチアーキテクチャー(multiple architectures)対応が可能です。 これは 1 つのイメージ内に、複数のアーキテクチャーのバリアント(variant; 異なる形式)を含めることができ、ときには Windows などのように異なるオペレーティングシステムを含めることができます。
マルチアーキテクチャーに対応したイメージを実行させたときには、OS やアーキテクチャーが合致するように、docker
が自動的にイメージ内のアーキテクチャーバリアントを選びます。
Docker Hub から提供されている Docker 公式イメージは、ほとんどが 複数アーキテクチャー に対応しています。
たとえばbusybox
イメージがサポートするアーキテクチャーはamd64
、arm32v5
、arm32v6
、arm32v7
、arm64v8
、i386
、ppc64le
、s390x
です。
このイメージをx86_64
あるいはamd64
マシン上で実行した場合、amd64
バリアントがプルされて実行されます。
Docker Desktop 上でのマルチアーキテクチャー対応
Docker Desktop はbinfmt_misc
マルチアーキテクチャーをサポートします。
これは、さまざまな Linux アーキテクチャー、arm
、mips
、ppc64le
、さらには s390x
でもコンテナーを実行することができます。
これを実現するのに、コンテナーそのものへの特別な設定は不要です。
Docker for Mac VM が提供する qemu-static を利用しているためです。
これがあるから、ARM コンテナーarm32v7
やppc64le
などのバリアントが busybox イメージにおいて実行できます。
Buildx を使ったマルチアーキテクチャー対応イメージのビルド
Docker によるコンテナー開発は、以前よりもさらに簡単になりました。 ARM のサーバーやデバイスについても同様です。 Docker の標準的なツールや処理手順を使って、数多くのコンピューターアーキテクチャー上において、イメージのビルド、プッシュ、プル、実行をシームレスに行うことができます。 ARM 向けのビルドを開始するにあたっては、Dockerfile やソースコードに変更を加える必要はほとんどありません。
Docker では、新しい CLI コマンドbuildx
が導入されました。
Docker Desktop for Mac あるいは Windows 上においてこのbuildx
コマンドを使えば、マルチアーキテクチャー対応のイメージをビルドし、マニフェストファイルをこれにひもづけることができます。
そしてこれらをまとめて 1 つのコマンドを実行するだけで、レジストリにプッシュすることができます。
内部で行われるエミュレーション機能により、ネイティブイメージ以外のものを、意識することなくビルドすることができます。
Buildx ではこれを実現するために、BuildKit にもとづくビルダーインスタンスを新たに加えています。
またネイティブ以外のバイナリーを実行するために Docker Desktop の技術基盤を活用しています。
Buildx の CLI コマンドの詳細は Buildx や docker buildx
コマンドラインリファレンス を参照してください。
マルチアーキテクチャーイメージのビルドと実行
docker buildx ls
コマンドを実行して、生成済みのビルダー一覧を確認します。
ここではデフォルトビルダーが表示されています。
これまでの古いビルダーを表わしています。
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
default * docker
default default running linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
マルチアーキテクチャー機能にアクセス可能な新たなビルダーを生成します。
$ docker buildx create --name mybuilder
mybuilder
あるいはdocker buildx create --name mybuilder --use
を実行すると、ビルダーを新規に生成するとともに、これを利用するように切り替える操作を、ただ 1 つのコマンドで実行できます。
新たなビルダーに切り替えて確認してみます。
$ docker buildx use mybuilder
$ docker buildx inspect --bootstrap
[+] Building 2.5s (1/1) FINISHED
=> [internal] booting buildkit 2.5s
=> => pulling image moby/buildkit:master 1.3s
=> => creating container buildx_buildkit_mybuilder0 1.2s
Name: mybuilder
Driver: docker-container
Nodes:
Name: mybuilder0
Endpoint: unix:///var/run/docker.sock
Status: running
Platforms: linux/amd64, linux/arm64, linux/arm/v7, linux/arm/v6
マルチアーキテクチャーイメージをビルド、プッシュ、実行するこの作業手順をテストしてみます。 そのために単純な Dockerfile を生成します。 いくつかのイメージバリアントをビルドして、Docker Hub にプッシュします。
以下に示す例では 1 つのDockerfile
を利用して、マルチアーキテクチャー対応の Ubuntu イメージをビルドして cURL をインストールするものです。
以下のようにしてDockerfile
を生成します。
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y curl
buildx を使って Dockerfile をビルドします。 実行にあたって、ビルドを行うアーキテクチャーの一覧を指定します。
$ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t username/demo:latest --push .
[+] Building 6.9s (19/19) FINISHED
...
=> => pushing layers 2.7s
=> => pushing manifest for docker.io/username/demo:latest 2.2
ここでusername
は有効な Docker のユーザー名です。
メモ
--platform
フラグは Buildx に対して、AMD 64-bit、Arm 64-bit、Armv7 の各アーキテクチャーの Linux イメージの生成を指示しています。--push
フラグは、マルチアーキテクチャーのマニフェストファイルを生成して、イメージとともに Docker Hub へのプッシュを行います。
docker buildx imagetools
を使ってイメージを確認します。
$ docker buildx imagetools inspect username/demo:latest
Name: docker.io/username/demo:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:2a2769e4a50db6ac4fa39cf7fb300fa26680aba6ae30f241bb3b6225858eab76
Manifests:
Name: docker.io/username/demo:latest@sha256:8f77afbf7c1268aab1ee7f6ce169bb0d96b86f585587d259583a10d5cd56edca
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Name: docker.io/username/demo:latest@sha256:2b77acdfea5dc5baa489ffab2a0b4a387666d1d526490e31845eb64e3e73ed20
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: docker.io/username/demo:latest@sha256:723c22f366ae44e419d12706453a544ae92711ae52f510e226f6467d8228d191
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
Docker Hub 上からusername/demo:latest
というタグにより、イメージが利用可能となりました。
このイメージを使って、Intel ノート PC、Amazon EC2 A1 インスタンス、Raspberry Pi などのアーキテクチャー上でのコンテナー実行が可能となりました。
Docker は、現状のアーキテクチャーに対応した正しいイメージをプルします。
したがって Raspberry Pi では 32 ビット ARM バージョン、EC2 A1 インスタンスでは 64 ビット ARM バージョンが動作します。
SHA タグは、各イメージバリアントを識別するものです。
Docker Desktop 上において、別アーキテクチャー向けのイメージを実行することもできます。
SHA タグを用いてイメージを実行することができ、アーキテクチャーの確認を行うことができます。 たとえば macOS 上において以下を実行します。
$ docker run --rm docker.io/username/demo:latest@sha256:2b77acdfea5dc5baa489ffab2a0b4a387666d1d526490e31845eb64e3e73ed20 uname -m
aarch64
$ docker run --rm docker.io/username/demo:latest@sha256:723c22f366ae44e419d12706453a544ae92711ae52f510e226f6467d8228d191 uname -m
armv7l
この例では、uname -m
から期待する戻り値は、それぞれaarch64
とarmv7l
です。
macOS または Windows のネイティブな開発マシン上において、このコマンドを実行していても、戻り値はこのようになります。