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を使うクロスコンパイルに切り替える