マルチ CPU アーキテクチャー対応の活用

読む時間の目安: 2 分

Docker イメージはマルチアーキテクチャー(multiple architectures)対応が可能です。 これは 1 つのイメージ内に、複数のアーキテクチャーのバリアント(variant; 異なる形式)を含めることができ、ときには Windows などのように異なるオペレーティングシステムを含めることができます。

マルチアーキテクチャーに対応したイメージを実行させたときには、OS やアーキテクチャーが合致するように、dockerが自動的にイメージ内のアーキテクチャーバリアントを選びます。

Docker Hub から提供されている Docker 公式イメージは、ほとんどが 複数アーキテクチャー に対応しています。 たとえばbusyboxイメージがサポートするアーキテクチャーはamd64arm32v5arm32v6arm32v7arm64v8i386ppc64les390xです。 このイメージをx86_64あるいはamd64マシン上で実行した場合、amd64バリアントがプルされて実行されます。

Docker Desktop 上でのマルチアーキテクチャー対応

Docker Desktopbinfmt_miscマルチアーキテクチャーをサポートします。 これは、さまざまな Linux アーキテクチャー、armmipsppc64le、さらには s390xでもコンテナーを実行することができます。

これを実現するのに、コンテナーそのものへの特別な設定は不要です。 Docker for Mac VM が提供する qemu-static を利用しているためです。 これがあるから、ARM コンテナーarm32v7ppc64leなどのバリアントが busybox イメージにおいて実行できます。

Buildx を使ったマルチアーキテクチャー対応イメージのビルド

Docker によるコンテナー開発は、以前よりもさらに簡単になりました。 ARM のサーバーやデバイスについても同様です。 Docker の標準的なツールや処理手順を使って、数多くのコンピューターアーキテクチャー上において、イメージのビルド、プッシュ、プル、実行をシームレスに行うことができます。 ARM 向けのビルドを開始するにあたっては、Dockerfile やソースコードに変更を加える必要はほとんどありません。

Docker では、新しい CLI コマンドbuildxが導入されました。 Docker Desktop for Mac あるいは Windows 上においてこのbuildxコマンドを使えば、マルチアーキテクチャー対応のイメージをビルドし、マニフェストファイルをこれにひもづけることができます。 そしてこれらをまとめて 1 つのコマンドを実行するだけで、レジストリにプッシュすることができます。 内部で行われるエミュレーション機能により、ネイティブイメージ以外のものを、意識することなくビルドすることができます。 Buildx ではこれを実現するために、BuildKit にもとづくビルダーインスタンスを新たに加えています。 またネイティブ以外のバイナリーを実行するために Docker Desktop の技術基盤を活用しています。

Buildx の CLI コマンドの詳細は Buildxdocker 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から期待する戻り値は、それぞれaarch64armv7lです。 macOS または Windows のネイティブな開発マシン上において、このコマンドを実行していても、戻り値はこのようになります。

mac, windows, Multi-CPU architecture support