「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できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
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
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"]
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
よくあるエラーと対処法
「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 |
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、docker buildxによるマルチアーキテクチャ設計からコンテナ本番運用まで実機ハンズオンで学べるDocker講座を用意しています。
→ Dockerマスター講座の詳細はこちら >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 次のページへ:DockerのENV・ARG・env_fileを正しく使う設計|ビルド時と実行時の値の渡し方とsecrets
- 前のページへ:プライベートDockerレジストリを構築する方法|registryコンテナの運用とDocker Hub rate limit対策
- この記事の属するカテゴリ:Dockerへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます