マルチ CPU アーキテクチャのサポートを活用

Docker イメージはマルチ・アーキテクチャ(multi-architecture)をサポートしています。つまり1つのイメージ内に、異なるアーキテクチャを含んでいたり、稀に Windows のような異なるオペレーティングシステムを含むことがあります。

マルチ・アーキテクチャをサポートしているイメージの実行時、 docker は自動的に OS とアーキテクチャに一致した、対応しているイメージを選択します。

Docker Hub 上の大部分の公式イメージには、 様々なアーキテクチャ があります。例えば、 busybox イメージがサポートするのは amd64arm32v6arm32v7arm64v8i386ppc64les390x です。このイメージを x86_64 / amd64 マシン上で実行しようとすると、 x86_64 対応版を自動的に取得・実行します。

Doker Desktopbinfmt_misc マルチ・アーキテクチャをサポートします。つまり、 armmipsppc64le のような異なる Linux アーキテクチャでコンテナを実行できるだけでなく、 x390x でさえもです。

Docker for Mac 仮想マシンqemu-static を使うので、コンテナ内で特別な設定は不要です。これにより、 busybox イメージの arm32v7ppc64le に対応した ARM コンテナを実行可能です。

Buildx [実験的機能]

現在の Docker は、 Arm サーバやデバイス向けのコンテナ開発が、以前よりも簡単になりました。標準的な Docker ツールや手順を用いて、異なるコンピュータ・アーキテクチャ上のイメージの開発、送信、受信、実行がシームレスに行えます。なお、Arm 向けにビルド開始しようとするとき、Dockerfile やソースコードに一切変更を加える必要はありません。

Docker には buildx という新しい CLI コマンドライン・ツールを導入しました。Docker Desktop for Mac と Windows では、この buildx コマンドを使うことで、複数のアーキテクチャに対応したイメージを構築し、マニフェスト・ファイルでそれらを一緒にし、コマンド1つでこれら全てを送信できます。エミュレーションを入れておけば、単にネイティブなイメージを作るよりも、透過的に構築できます。Buildx はこれらを行うため、 BuildKit をベースとする新しい構築インスタンスを追加しました。そして、Docker Desktop の技術スタックによって、ネイティブではないバイナリも実行します。

Buildx CLI コマンドに関する詳しい情報は Buildx をご覧ください。

インストール

1. Docker Desktop の最新バージョンをダウンロードします。

2. 画面の指示に従い、インストール手順を完了します。Docker Desktop のインストールに成功したら、タスクトレイ内に Docker のアイコンが見えます。

3. Docker メニューから About Docker Desktop をクリックし、インストールした Docker Desktop のバージョンが 2.0.4.0 (33772) 以上かどうかを確認します。

マルチ・アーキテクチャ・イメージの構築と実行

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

あるいは、新しいビルダーを作成してコマンド1つで切り替えるには docker buildx create --name mybuilder --use を実行します。

新しいビルダーに切り替えて調べてみましょう。

$ 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 を作成し、2つの派生イメージを作成し、それらを Docker Hub に送信します。

$ mkdir test && cd test && cat <<EOF > Dockerfile

FROM ubuntu
RUN apt-get update && apt-get install -y curl
WORKDIR /src
COPY . .
EOF
$ 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 に送信します。

イメージの調査には 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 Pis や、その他のアーキテクチャ上でコンテナを実行できます。Docker はイメージ取得時、各々のアーキテクチャに対応したものをダウンロードします。そのため、 Raspberry Pi では 32-bit Arm バージョンを実行し、EC2 A1 インスタンスでは 64-bit 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 -a の実行結果が aarch64armv7l になっているだけでなく、各コマンドが macOS 開発マシン上でネイティブに実行しています。

参考

Leverage multi-CPU architecture support
https://docs.docker.com/docker-for-mac/networking/