2026年5月29日

2026年5月29日

Docker buildxでマルチアーキテクチャイメージを作る方法|amd64とarm64を1つのタグで配布する

Intel/AMDのサーバー(amd64)とArmのサーバー(arm64:AWS Graviton、Apple シリコンのMac、Raspberry Pi 4以降の64ビットOSなど)の両方で同じイメージを使いたい場合、マルチアーキテクチャ(マルチプラットフォーム)イメージ を作ります。

マルチプラットフォームイメージは、アーキテクチャごとのイメージをまとめた一覧(イメージインデックス、マニフェストリスト)として1つのタグに登録されます。docker pull や docker run は、実行するマシンに合ったイメージを自動で選びます。

この記事では、Docker の buildx(BuildKitを使うビルドコマンド)で、amd64とarm64のイメージをまとめてビルドし、レジストリに公開する手順を説明します。内容は2026年10月時点のDocker公式ドキュメントで確認しています。

前提:buildxが使えるか確認する

Docker Desktop(Windows・Mac)にはbuildxが含まれています。LinuxのDocker Engineでは、Docker公式リポジトリからインストールした場合、docker-buildx-plugin パッケージとして入ります。

docker buildx version

# 入っていない場合(Docker公式のaptリポジトリを使っているUbuntu/Debian)
sudo apt install docker-buildx-plugin

方法を選ぶ

複数のアーキテクチャ向けにビルドする方法は3つあります。

方法 仕組み 向いている場面
QEMUによるエミュレーション 別アーキテクチャの命令をエミュレーターで実行する。Dockerfileの変更は不要 まず試すとき。RUN の処理が軽いイメージ
クロスコンパイル ビルドするマシンのアーキテクチャのままで、別アーキテクチャ向けのバイナリを作る Go・Rustなど、コンパイルが重い言語
複数のネイティブノード amd64とarm64の実機をビルダーにまとめ、それぞれのアーキテクチャをそのマシンでビルドする 大規模なビルド、エミュレーションでは動かない処理

エミュレーションは手軽ですが、計算量の多い処理ではネイティブより大幅に遅くなります。

また、ビルドの実行役(ビルダー)の種類によって、マルチプラットフォームイメージを扱えるかが変わります。

ビルダー(ドライバー) マルチプラットフォーム ビルド結果をローカルのイメージ一覧に入れるか
docker(既定のビルダー) containerdイメージストアを使っている場合のみ可 入れる
docker-container 可 入れない(--push でレジストリに送るか、--load を付ける)

Docker Desktop と、新しくインストールした Docker Engine 29.0 以降は、containerdイメージストアが既定で使われます。古いバージョンから更新したDocker Engineでは、従来のイメージストアのままです。どちらを使っているかは次のコマンドで確認できます。

docker info -f '{{ .DriverStatus }}'
# containerdイメージストアの場合、[[driver-type io.containerd.snapshotter.v1]] が含まれる

以下では、どちらの環境でも使える docker-container ビルダーでの手順を説明し、そのあとで既定のビルダーを使う場合を補足します。

手順1:docker-containerビルダーを作る

docker buildx create \
  --name container-builder \
  --driver docker-container \
  --bootstrap --use

--use で、以後の docker buildx build がこのビルダーを使うようになります。ビルダーが対応しているプラットフォームを確認します。

docker buildx ls
docker buildx inspect --bootstrap

Platforms: の行に linux/amd64 と linux/arm64 が含まれていれば、両方のビルドができます。

手順2:エミュレーターを確認する(Linux)

Docker Desktopにはエミュレーター(QEMU)が組み込まれているので、この手順は不要です。

LinuxのDocker Engineでも、docker-container ビルダーにはエミュレーターが同梱されています。上の Platforms: に目的のアーキテクチャが出ない場合や、ビルド中に exec format error が出る場合は、ホストにQEMUを登録します。

docker run --privileged --rm tonistiigi/binfmt --install all

このコマンドはQEMUのバイナリをホストのカーネルの binfmt_misc に登録します。--privileged でホストの設定を変えるので、自分で管理しているマシンでだけ実行してください。

手順3:ビルドしてレジストリに公開する

docker-container ビルダーの結果はローカルのイメージ一覧に入らないため、--push でレジストリに直接送ります。先にレジストリにログインしておきます。

docker login

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t yourname/myapp:1.0 \
  --push .

yourname/myapp は、Docker Hubのユーザー名とリポジトリ名に置き換えます。GitHub Container Registryなど他のレジストリでは、ghcr.io/yourname/myapp:1.0 のようにレジストリのホスト名から書きます。

FROM に指定したベースイメージも、目的のアーキテクチャに対応している必要があります。公式イメージの多くは amd64 と arm64 の両方を提供していますが、対応していないイメージを使うとビルドが失敗します。

手順4:公開したイメージを確認する

レジストリに登録されたイメージの中身(どのアーキテクチャが含まれているか)を確認します。

docker buildx imagetools inspect yourname/myapp:1.0

出力の Manifests: に、Platform: linux/amd64 と Platform: linux/arm64 のイメージが並んでいれば成功です。

別アーキテクチャのイメージが実際に動くかは、--platform を付けて実行して確かめられます(エミュレーターが必要です)。

docker run --rm --platform linux/arm64 yourname/myapp:1.0 uname -m
# aarch64 と表示されれば arm64 のイメージが動いている

ローカルで試すときは1つのプラットフォームを --load する

公開する前に手元で動作を確かめたい場合、従来のイメージストアでは、複数のプラットフォームをまとめてローカルに読み込むことはできません。1つのプラットフォームを指定して --load します。

docker buildx build --platform linux/arm64 -t myapp:arm64-test --load .
docker run --rm myapp:arm64-test

既定のビルダーでビルドする(containerdイメージストアの場合)

containerdイメージストアを使っている環境では、ビルダーを作らずに既定の docker ビルダーでマルチプラットフォームイメージを作れます。結果はローカルのイメージ一覧に入ります。

# 既定のビルダーに戻す(Docker Engine の場合)
docker buildx use default

docker buildx build --platform linux/amd64,linux/arm64 -t yourname/myapp:1.0 .
docker push yourname/myapp:1.0

既定のビルダーの名前は環境によって異なります。Docker Desktopでは desktop-linux などのコンテキスト名になっているので、docker buildx ls で docker ドライバーと表示されるビルダーの名前を確認して docker buildx use に指定してください。

古いDocker Engineで containerd イメージストアに切り替えるには、/etc/docker/daemon.json に次の設定を加えて Docker を再起動します。

{
  "features": {
    "containerd-snapshotter": true
  }
}

イメージの保存方式が変わるため、既存のイメージやコンテナを使っているサーバーで切り替える場合は、公式ドキュメントの注意事項を読んでから行ってください。

クロスコンパイルで速くする

エミュレーションでのビルドが遅い場合は、Dockerfileを書き換えてクロスコンパイルにします。buildxは、ビルドするマシンのプラットフォームを BUILDPLATFORM、目的のプラットフォームを TARGETPLATFORM・TARGETOS・TARGETARCH という引数で渡します。Goの例です。

# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /app
COPY . .
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o server .

FROM alpine
COPY --from=build /app/server /server
ENTRYPOINT ["/server"]

ビルド用のステージは --platform=$BUILDPLATFORM でビルドするマシンと同じアーキテクチャで動き、GOOS・GOARCH で目的のアーキテクチャ向けにコンパイルします。最後のステージ(FROM alpine)だけが目的のアーキテクチャのイメージになります。マルチステージビルドの書き方は Dockerのマルチステージビルドの使い方 を参照してください。

うまくいかないときの確認

症状 確認すること
「docker ドライバーではマルチプラットフォームのビルドに対応していない」という趣旨のエラー 既定のビルダーで、containerdイメージストアを使っていない。docker-container ビルダーを作って --use するか、containerdイメージストアに切り替える
exec format error 別アーキテクチャの命令を実行できていない。tonistiigi/binfmt --install all でQEMUを登録する
ビルドは成功したのにイメージが docker images に無い docker-container ビルダーは結果をローカルに入れない。--push するか、1つのプラットフォームで --load する
--push で denied などの権限エラー docker login しているか。タグのユーザー名・レジストリ名が自分のものか
ベースイメージの取得で no match for platform in manifest ベースイメージが目的のアーキテクチャに対応していない。docker buildx imagetools inspect ベースイメージ で対応状況を確認する
arm64のビルドが非常に遅い エミュレーションで重い処理を実行している。クロスコンパイルにするか、arm64の実機をビルダーに加える

使い終わったビルダーは削除できます。削除したあとは、既定のビルダーが使われます(docker buildx ls で * が付いているものが現在のビルダーです)。

docker buildx rm container-builder
docker buildx ls

まとめ

  • マルチプラットフォームイメージは、アーキテクチャごとのイメージを1つのタグにまとめたもので、実行するマシンに合ったものが自動で選ばれる
  • docker buildx create --driver docker-container --use でビルダーを作り、--platform linux/amd64,linux/arm64 --push でビルドと公開を行う
  • 既定のビルダーでも、containerdイメージストアを使っていればマルチプラットフォームのビルドができる
  • docker buildx imagetools inspect で、公開したイメージに含まれるアーキテクチャを確認する
  • エミュレーションが遅い場合は、BUILDPLATFORM・TARGETARCH を使うクロスコンパイルに切り替える

関連記事

お気軽にご相談ください

お見積りへ お問い合わせへ
▲