docker buildxでマルチアーキテクチャイメージをビルドする方法|ARM・x86両対応のビルド設計

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Docker > docker buildxでマルチアーキテクチャイメージをビルドする方法|ARM・x86両対応のビルド設計
「Raspberry Pi向けに作ったDockerイメージが、x86の本番サーバーでまったく動かない」
「AWS GravitonのARM64インスタンスに移行したいが、既存のイメージがamd64専用で使えない」

そう困っているなら、docker buildxのマルチアーキテクチャビルドが解決策です。
docker buildxを使えば、linux/amd64とlinux/arm64の両方に対応したイメージを1回のビルドで作成し、Docker Hubにpushできます。

この記事では、BuildKitとbuildxの関係から、QEMU設定、builderインスタンスの作成、実際のマルチプラットフォームビルド、Dockerfile内のARG TARGETARCH活用まで、実際のコマンド出力を交えて解説します。

動作確認環境: Ubuntu 24.04 LTS / Rocky Linux 9.4(Docker Engine 27.x・buildx v0.17.x)

この記事のポイント

・docker buildx build --platform linux/amd64,linux/arm64 で両アーキに対応できる
・QEMUを使うとx86マシン上でもARMイメージをクロスビルドできる
・ARG TARGETARCHをDockerfileに組み込むとアーキ別バイナリ配置を自動化できる
・--push オプションでビルドと同時にDocker Hubへマルチプラットフォームpushできる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

docker buildxとは何か(従来のdocker buildとの違い)

従来の docker build はホストマシンのアーキテクチャ向けイメージしか作れません。x86_64マシンで docker build を実行すると、linux/amd64のイメージが作られます。ARM64向けのRaspberry PiやAWS Gravitonで動かすには、ARM64マシン上で別途ビルドし直す必要がありました。

docker buildx はDockerが提供するビルド拡張プラグインです。BuildKitをバックエンドに使い、複数のアーキテクチャを1回のビルドコマンドで同時にターゲットにできます。Docker Engine 23.0以降ではbuildxはデフォルトで同梱されており、docker buildx version ですぐに確認できます。

従来のdocker buildとbuildxの主な違い

マルチプラットフォーム対応:--platform linux/amd64,linux/arm64 のように複数アーキを同時に指定できる
BuildKitバックエンド:依存のない命令を並列実行し、ビルドを高速化する
リモートbuilderのサポート:docker-containerドライバやKubernetesドライバで外部ビルド環境を利用できる
--push オプション:ビルドと同時にDocker Hubやプライベートレジストリにpushできる

# buildxのバージョン確認 $ docker buildx version github.com/docker/buildx v0.17.1 ... # 現在のbuilderを確認 $ docker buildx ls NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS default * docker running v0.14.2 linux/amd64, linux/amd64/v2, linux/386

BuildKitとbuildxの関係を理解する

BuildKitはDockerのビルドエンジンを刷新した実装で、Docker 18.09から利用できるようになりました。従来のビルドエンジンとの主な違いは以下のとおりです。
並列実行:依存関係のない命令を同時に処理してビルド時間を短縮する
未使用ステージのスキップ:マルチステージビルドで実際に使わないステージを実行しない
キャッシュマウント:RUN --mount=type=cache でパッケージキャッシュを永続化できる
マルチプラットフォームビルド:QEMUと組み合わせて異なるアーキテクチャ向けにビルドできる

docker buildxはこのBuildKitをオーケストレーションするCLIプラグインです。buildxが「どのプラットフォームでビルドするか」「どのbuilderインスタンスを使うか」を管理し、BuildKitが実際のビルド処理を担当します。デフォルトのdockerドライバはマルチプラットフォームをサポートしていないため、マルチアーキテクチャビルドには専用のbuilderインスタンスの作成が必要です。

マルチアーキテクチャビルドの仕組み(QEMU・クロスコンパイル)

マルチアーキテクチャビルドには2つのアプローチがあります。それぞれの特徴を理解した上で使い分けることが重要です。

1. QEMUエミュレーション(手軽・汎用)

x86マシン上でLinuxカーネルの binfmt_misc 機能を使い、ARMバイナリをQEMUで透過的に実行する方式です。
設定が簡単で、Dockerfileを変更しなくてもARMイメージをビルドできます。ただし、エミュレーションのオーバーヘッドがあるため、C/C++の重いコンパイル処理には不向きです。シェルスクリプト主体の軽量イメージやPython/Rubyアプリに向いています。

2. ネイティブクロスコンパイル(高速・Go向き)

ARG TARGETARCH を使ってDockerfile内でアーキテクチャを判定し、ビルダーステージはホスト(amd64)のままクロスコンパイルを行う方式です。
GoやRustのようにクロスコンパイルをネイティブサポートする言語では、QEMUなしで高速にARMイメージを作れます。CI環境でのビルド時間を大幅に短縮できるため、本番運用ではこちらを優先するのが現場の鉄則です。

どちらを選ぶか

方式 向いているケース 注意点
QEMUエミュレーション スクリプト系・パッケージインストール主体のイメージ C/C++ビルドは大幅に遅くなる
ネイティブクロスコンパイル Go・Rust・静的バイナリを含むイメージ Dockerfileに TARGETOS/TARGETARCH の記述が必要

buildxのセットアップ手順(builder instanceの作成)

デフォルトのbuilderはマルチアーキテクチャビルドをサポートしていません。docker-containerドライバを使う専用のbuilderインスタンスを作成します。

1. QEMUのインストール(binfmt_misc設定)

DockerイメージでQEMUをインストールする方法が最も確実です。任意のLinuxホストで以下を実行します。

# Dockerが提供するbinfmtイメージでQEMUを設定する(推奨) $ docker run --rm --privileged tonistiigi/binfmt --install all installing: arm64 OK installing: arm OK installing: riscv64 OK installing: ppc64le OK installing: s390x OK # 設定確認 $ ls /proc/sys/fs/binfmt_misc/ | grep qemu qemu-aarch64 qemu-arm qemu-riscv64

2. builder instanceの作成と有効化

docker-containerドライバのbuilderインスタンスを作成します。このbuilderはDockerコンテナとして起動し、BuildKitを内包した状態でビルドを処理します。

# multiarch-builder という名前でbuilderを作成し、すぐにアクティブにする $ docker buildx create --name multiarch-builder --driver docker-container --use multiarch-builder # builderを起動し、対応プラットフォームを確認する $ docker buildx inspect --bootstrap Name: multiarch-builder Driver: docker-container Nodes: Name: multiarch-builder0 Endpoint: unix:///var/run/docker.sock Status: running Buildkit: v0.15.2 Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64

Platforms の欄に linux/arm64 が含まれていれば設定成功です。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、docker buildxを使ったマルチアーキテクチャビルドの設計・運用まで体系的に学べるDocker講座を用意しています。
Dockerマスター講座の詳細はこちら >>

linux/amd64とlinux/arm64両対応イメージをビルドする

builderインスタンスの準備ができたら、マルチプラットフォームビルドを実行します。

# amd64とarm64の両方に対応したイメージをビルドしてpushする $ docker buildx build \ --platform linux/amd64,linux/arm64 \ --tag yourname/myapp:1.0 \ --push \ . [+] Building 45.3s (20/20) FINISHED => [linux/amd64 internal] load build definition from Dockerfile 0.0s => [linux/arm64 internal] load build definition from Dockerfile 0.0s => [linux/amd64 1/4] FROM ubuntu:24.04@sha256:3d1556a... 13.2s => [linux/arm64 1/4] FROM ubuntu:24.04@sha256:3d1556a... 15.8s => [linux/amd64 2/4] RUN apt-get update && apt-get install -y curl 18.4s => [linux/arm64 2/4] RUN apt-get update && apt-get install -y curl 31.2s => pushing manifest for docker.io/yourname/myapp:1.0 1.9s

オプションの使い分け:
--push:複数プラットフォームを一括でDocker Hubにpushする(本番用途はこちら)
--load:1プラットフォームのみをローカルのdocker imagesに読み込む(動作確認時)
--output type=image,push=true:--push と同等。プライベートレジストリ指定時に使う

注意:--platform で複数プラットフォームを指定した場合、--load は使えません。--push--output を使ってください。

Docker Hubへのマルチプラットフォームイメージのpush

pushしたイメージをdocker buildx imagetools inspectで確認すると、各プラットフォームへの対応状況がわかります。

# pushしたマルチプラットフォームイメージの内容を確認する $ docker buildx imagetools inspect yourname/myapp:1.0 Name: docker.io/yourname/myapp:1.0 MediaType: application/vnd.oci.image.index.v1+json Digest: sha256:abc123def456789... Manifests: Name: docker.io/yourname/myapp:1.0@sha256:aaa111... MediaType: application/vnd.oci.image.manifest.v1+json Platform: linux/amd64 Name: docker.io/yourname/myapp:1.0@sha256:bbb222... MediaType: application/vnd.oci.image.manifest.v1+json Platform: linux/arm64

docker pull yourname/myapp:1.0 を実行したユーザーのDocker環境が自動的に自分のアーキテクチャを検出し、対応するイメージを取得します。x86マシンからpullすればamd64イメージが、Raspberry Piからpullすればarm64イメージが届きます。

Dockerfile設計のポイント(ARG TARGETARCH活用)

docker buildx でマルチプラットフォームビルドを実行すると、以下のビルドARGが自動的に設定されます。
TARGETPLATFORM:例: linux/arm64
TARGETOS:例: linux
TARGETARCH:例: arm64(amd64 / arm64 / arm / riscv64 など)
TARGETVARIANT:例: v8(armv7の場合は v7

これらのARGをDockerfileで参照することで、アーキテクチャ別のバイナリ配置やビルド設定を自動化できます。

1. アーキテクチャ別バイナリを取得するDockerfileの例

FROM ubuntu:24.04 # ARGを宣言するとbuildxがアーキ情報を自動的にセットする ARG TARGETARCH RUN apt-get update && apt-get install -y curl ca-certificates # アーキテクチャに応じて配布バイナリを切り替える RUN case "$TARGETARCH" in \ amd64) ARCH="x86_64" ;; \ arm64) ARCH="aarch64" ;; \ arm) ARCH="armhf" ;; \ *) echo "Unsupported arch: $TARGETARCH"; exit 1 ;; \ esac && \ curl -Lo /usr/local/bin/myapp \ "https://example.com/releases/myapp-linux-${ARCH}" && \ chmod +x /usr/local/bin/myapp CMD ["/usr/local/bin/myapp"]

2. Goアプリのクロスコンパイルを使ったマルチステージビルド

GoはCGO_ENABLED=0かつGOOS・GOARCHを指定するだけでクロスコンパイルが完了します。ビルダーステージはホストのamd64で動き、エミュレーション不要のため高速です。

# ビルダーステージ: ホスト(amd64)上でクロスコンパイルするためQEMU不要 FROM golang:1.22 AS builder ARG TARGETOS ARG TARGETARCH WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . # CGO_ENABLED=0でクロスコンパイル。GOARCHにTARGETARCHが入る RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ go build -o /app/server ./cmd/server # ランナーステージ: 最小構成のイメージにバイナリだけをコピーする FROM debian:bookworm-slim COPY --from=builder /app/server /usr/local/bin/server CMD ["/usr/local/bin/server"]

このパターンはCI環境でのビルド時間を大幅に短縮します。QEMUエミュレーションでGoアプリをビルドした場合に比べ、10倍以上高速になることもあります。

Raspberry Pi・Graviton環境での動作確認

ビルドしたマルチアーキテクチャイメージが、Raspberry Pi 4(linux/arm64)やAWS Graviton3(linux/arm64)で正しく動くか確認します。

# Raspberry Pi 4 / AWS Graviton インスタンスで確認 $ docker pull yourname/myapp:1.0 1.0: Pulling from yourname/myapp a1d0c7532777: Pull complete Status: Downloaded newer image for yourname/myapp:1.0 docker.io/yourname/myapp:1.0 # ARM64環境では aarch64 が返る $ docker run --rm yourname/myapp:1.0 uname -m aarch64 # docker inspectでアーキテクチャを確認する $ docker inspect --format '{{.Architecture}}' yourname/myapp:1.0 arm64

x86検証機で linux/amd64 として動作確認した後、同じタグのイメージをARMの検証機でpullすると arm64 のイメージが自動的に取得されます。「アーキテクチャによって挙動が変わる」問題は、このように実機で必ず確認するようにしてください。

よくあるエラーと対処法

「multiple platforms feature is currently not supported for docker driver」

デフォルトのdockerドライバはマルチプラットフォームに対応していません。docker-containerドライバのbuilderインスタンスを作成し、--use で切り替えてから再実行してください。

# 新しいbuilderを作成してアクティブにする $ docker buildx create --name multiarch-builder --driver docker-container --use # 現在のbuilderを確認する $ docker buildx ls NAME/NODE DRIVER/ENDPOINT STATUS multiarch-builder * docker-container running default docker running

「qemu: uncaught target signal 4(Illegal instruction)」

QEMUのバージョンが古い、またはbinfmt_miscが正しく設定されていないケースです。以下のコマンドでQEMUを再インストールすることで解決する場合がほとんどです。

# QEMUを再インストールして設定をリセットする $ docker run --rm --privileged tonistiigi/binfmt --uninstall qemu-* $ docker run --rm --privileged tonistiigi/binfmt --install all

「--load option can't be used with multiple platforms」

--load は1プラットフォームのみに対応しています。複数プラットフォームを指定した場合は --push を使ってください。動作確認だけしたい場合は、一時的に1プラットフォームだけ指定してビルドします。

# 動作確認用: 1プラットフォームのみ --load する $ docker buildx build --platform linux/arm64 --tag myapp:test --load . # ローカルに読み込めたか確認する $ docker images myapp REPOSITORY TAG IMAGE ID CREATED SIZE myapp test abc123def456 1 minute ago 80.5MB

ARMイメージのビルドが極端に遅い

QEMUエミュレーションによる性能低下です。C/C++の重いコンパイル処理はエミュレーションで10倍以上遅くなることがあります。GoやRustのように言語レベルでクロスコンパイルをサポートするものは、ARG TARGETARCH を使ったネイティブクロスコンパイルに切り替えることでビルド時間を大幅に削減できます。

本記事のまとめ

docker buildxのマルチアーキテクチャビルドの主要コマンドと手順をまとめます。
やりたいこと コマンド
QEMUのセットアップ docker run --rm --privileged tonistiigi/binfmt --install all
builderインスタンスの作成 docker buildx create --name multiarch-builder --driver docker-container --use
builderの起動・確認 docker buildx inspect --bootstrap
マルチプラットフォームビルド+push docker buildx build --platform linux/amd64,linux/arm64 -t image:tag --push .
pushしたイメージのアーキ確認 docker buildx imagetools inspect image:tag
使用するbuilderの切り替え docker buildx use multiarch-builder
builderの削除 docker buildx rm multiarch-builder
docker buildxを使えば、Raspberry Pi・AWS GravitonなどARM環境向けのイメージをx86の開発機から一括でビルド・配布できます。GoアプリはARG TARGETARCHとクロスコンパイルを組み合わせることで、QEMUのオーバーヘッドなしに高速なCIビルドを実現できます。まず手元のx86環境でbuilderインスタンスを作り、小さなサンプルイメージで動作確認することから始めてみてください。

現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、docker buildxによるマルチアーキテクチャ設計からコンテナ本番運用まで実機ハンズオンで学べるDocker講座を用意しています。
Dockerマスター講座の詳細はこちら >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。