Docker Buildx マルチアーキテクチャイメージ:2026年のリモート Mac CI をどう構成するか
Apple SiliconのリモートMacをARM64の常駐ビルダーとして使い、AMD64は原生ノードまたは交差コンパイルへ分担させる構成を解説します。Buildxの作成、初回ビルド、CI接続、キャッシュ、Manifest、再起動後の復旧まで、停止条件を含む導入手順にまとめています。
目次
Apple SiliconのリモートMacはARM64をネイティブにビルドする常駐Builderとして使い、AMD64までQEMUで無理に処理させない構成を選んでください。今週は小さなDockerfileでARM64の実行確認を行い、その後にAMD64ノードまたは交差コンパイル経路を加え、最後にManifestと再起動復旧を検証します。
ARM64とAMD64を継続的に公開するDevOps・プラットフォーム担当者向けの記事です。QEMU経由のコンパイルが遅い、依存ライブラリが不安定、CIノードが再起動後に戻らない、といった問題を抱えている場合に、Builderの役割分担を決める材料になります。
失敗しやすい構成を先に切り分ける
単一のARM Macからすべての対象プラットフォームをQEMUで構築すると、Dockerfile内のコンパイルや圧縮処理だけが極端に遅くなったり、ARM64上では見えなかったAMD64固有の依存関係が公開直前に発覚したりします。Docker公式は、マルチプラットフォーム構築の方式として、QEMUエミュレーション、複数のネイティブノード、クロスコンパイルを示しています。公式の方式比較
ここで混同してはいけないのは、ホストのCPUアーキテクチャ、Builderノードのプラットフォーム、生成するイメージの対象プラットフォーム、コンテナ内で実際にコンパイルするアーキテクチャです。Apple Silicon上でAMD64用イメージを出力できても、それはAMD64のネイティブ実行を意味しません。
| 構成 | ARM64ビルド | AMD64ビルド | 適する条件 | 評価 |
|---|---|---|---|---|
| ARM Mac + QEMU | ネイティブ | エミュレーション | 小規模な検証、依存が少ないDockerfile | 条件付き |
| ARM Mac + AMD64ノード | ネイティブ | ネイティブ | 継続的な公開、コンパイル処理が重い | 推奨 |
| ARM Mac + 交差コンパイル | ネイティブ | コンパイラー次第 | Goなど対象分離が明確な構成 | 条件付き |
| ARM Macのみ | ネイティブ | QEMU依存 | 予算やノード数を抑えた試行 | 限定利用 |
Apple SiliconのMacからlinux/amd64イメージを直接作成できますか。
作成できます。ただし、Apple Silicon上のDockerがAMD64命令をネイティブに実行するわけではなく、通常はQEMUを介したエミュレーションです。Docker公式も、エミュレーションは簡単に始められる一方、コンパイル処理ではネイティブノードやクロスコンパイルが有利になる場合があると説明しています。マルチプラットフォーム構築の公式説明
第一段階:遠隔Macの役割と接続経路を固定する
最初に、既存CIのログから対象プラットフォーム、失敗したDockerfileの命令、キャッシュのヒット状況を抽出します。AMD64のコンパイルだけが失敗しているなら、Macを増強する前にAMD64ネイティブノードを追加する方が原因を分離しやすいです。
Docker DesktopはmacOSで利用でき、BuildxもDocker環境に含まれます。ただし、CLIでdocker buildxが表示されることと、実際にノードが利用可能であることは別です。macOS向けDocker Desktopの導入条件
次の値は実環境の情報に置き換えてください。ホスト名、ユーザー名、Context名、Builder名、レジストリ名、トークンを固定文字列のまま運用してはいけません。
export MAC_HOST="<MAC_HOST>"
export CI_USER="<CI_USER>"
export MAC_CONTEXT="<MAC_CONTEXT>"
export BUILDER_NAME="<BUILDER_NAME>"
export IMAGE="<REGISTRY>/<NAMESPACE>/<IMAGE>:<TAG>"
docker context create "$MAC_CONTEXT" \
--docker "host=ssh://${CI_USER}@${MAC_HOST}"
docker buildx create "$MAC_CONTEXT" \
--name "$BUILDER_NAME" \
--driver docker-container \
--use
docker buildx inspect "$BUILDER_NAME" --bootstrap
SSH経路はCI専用アカウント、鍵認証、必要最小限の権限に分けてください。DockerソケットやSSHの公開範囲を広げるのではなく、Docker公式のアクセス保護方針に沿って管理します。Docker EngineのSSHアクセス保護
Docker BuildxではQEMUとネイティブARM64ノードのどちらを選ぶべきですか。
依存関係の確認や軽量な成果物ならQEMUで開始できますが、継続的なコンパイル、圧縮、ネイティブ拡張の生成があるならARM64はApple Siliconで、AMD64はAMD64ノードで処理してください。Macを「すべてを代行するマシン」ではなく、ARM64担当のノードとして扱うことが停止条件を明確にします。
第二段階:最小イメージでBuilderを検証する
実プロジェクトをいきなり接続せず、まずプラットフォーム識別だけを確認できるDockerfileを用意します。
FROM --platform=$BUILDPLATFORM alpine:3.20
ARG TARGETPLATFORM
ARG TARGETARCH
RUN printf 'target=%s arch=%s\n' "$TARGETPLATFORM" "$TARGETARCH"
Dockerfile内のベースイメージ、コンパイラー、実行テストがどのアーキテクチャで動くかを分けて記録します。BuildKitでは、ビルド用プラットフォームと成果物の対象プラットフォームを分離する設計が可能です。実際のプロジェクトでは、BUILDPLATFORM、TARGETPLATFORM、TARGETARCHを使う箇所を確認し、交差コンパイルに対応していない依存処理を特定してください。
docker buildx build \
--builder "$BUILDER_NAME" \
--platform linux/arm64 \
--tag "$IMAGE-arm64" \
--push .
docker buildx build \
--builder "$BUILDER_NAME" \
--platform linux/amd64 \
--tag "$IMAGE-amd64" \
--push .
終了コードだけでは公開成功と判断しません。各タグを実行し、生成されたイメージのOS、アーキテクチャ、エントリーポイントを確認します。Buildxのノード追加は公式のbuildx create仕様に従い、追加後は必ずBootstrap状態を記録します。複数ノードBuilderの公式コマンド
第三段階:分担、キャッシュ、ManifestをCIに組み込む
遠隔MacをBuildxの複数ノードBuilderへ追加するにはどうしますか。
MacへのSSH接続用Contextを作成し、そのContextをBuilderのノードとして指定します。CI実行ユーザーが対話式のログイン状態やローカルのDocker認証に依存しないよう、Context、Builder、レジストリ認証をジョブ内で明示的に準備してください。
構成例では、ARM64ジョブを<MAC_CONTEXT>へ、AMD64ジョブを<AMD64_CONTEXT>へ振り分けます。単一の共有Builderに並列ジョブを集中させる場合は、Dockerの作業領域、ディスク容量、同時実行数を確認し、競合するプロジェクトはBuilderを分けます。
キャッシュは最終イメージとは別の参照に保存します。例えば、ARM64とAMD64で同じキャッシュ参照を上書きすると、片方のレイヤーが期待どおり再利用されない可能性があります。Registry、ローカル、GitHub Actionsなどのキャッシュバックエンドには対応条件があるため、利用するドライバーと保存先を先に確認してください。Build cacheの公式バックエンド一覧
docker buildx build \
--builder "$BUILDER_NAME" \
--platform linux/arm64 \
--cache-from type=registry,ref="<REGISTRY>/<CACHE>:arm64" \
--cache-to type=registry,ref="<REGISTRY>/<CACHE>:arm64",mode=max \
--tag "$IMAGE-arm64" \
--push .
各プラットフォームのイメージを別タグへ公開した後、Manifestを作成します。
docker buildx imagetools create \
--tag "$IMAGE" \
"$IMAGE-arm64" \
"$IMAGE-amd64"
Manifestの作成方法はDocker公式のimagetools create仕様に合わせます。Manifest統合の公式リファレンス その後、公開された参照に両方の対象が含まれるかを検査します。
docker buildx imagetools inspect "$IMAGE"
linux/arm64とlinux/amd64の両方が表示され、各環境でコンテナが起動することを合格条件にします。Manifest確認の公式リファレンス
第四段階:常駐運用と再起動後の復旧を確認する
MacをCIノードにする場合、SSH接続が切れてもビルドが継続するかを確認します。さらに、Docker Desktop、Context、Builder、レジストリ認証、キャッシュ参照がMacの再起動後に復旧するかを別々に検証してください。
BuildxやBuildKitのバージョンを固定する場合は、Docker Desktopの更新だけで挙動が変わらないかを確認します。Buildxのリリース情報は公式リポジトリで確認し、更新前に代表的なDockerfileを隔離ノードで実行します。Buildx公式リリース一覧
注意:Macが再起動した後にBuilderだけ再作成され、レジストリ認証やキャッシュ設定が失われる構成は、通常時の成功ログだけでは発見できません。再起動を含む復旧テストを、正式登録前の必須条件にしてください。
次のチェックをすべて完了できなければ、正式な公開ノードへ移行しません。
- [ ] ホストのCPU、Builderノードのプラットフォーム、対象イメージのプラットフォームを記録した
- [ ] CI専用アカウントとSSH鍵を用意し、管理用の別経路を残した
- [ ]
docker buildx inspect --bootstrapで各ノードを確認した - [ ] ARM64とAMD64を別々にビルドし、各イメージを実行した
- [ ] キャッシュ参照をプラットフォーム別または用途別に分離した
- [ ] Manifest検査で両方のプラットフォームを確認した
- [ ] SSH切断後もジョブが完了した
- [ ] Mac再起動後にDocker、Builder、認証、キャッシュが復旧した
- [ ] ノード停止時に不完全なManifestを公開しない処理を確認した
- [ ] Buildx、Docker Desktop、BuildKit更新時の切り戻し手順を記録した
最終段階:単一Mac、混合ノード、交差コンパイルを判定する
評価は単なるビルド時間ではなく、実プロジェクトで次の証拠を並べて決めます。ジョブ成功、キャッシュ再利用、ARM64とAMD64双方での起動、ノード停止時の公開停止、再起動後の復旧が揃っているかを見ます。
ARM64の検証と常駐ジョブが中心で、AMD64側に重いコンパイルがないなら、Apple SiliconのリモートMac単独構成を小規模に維持できます。AMD64のエミュレーションで失敗する命令がある、またはキャッシュを使ってもコンパイル負荷が集中するなら、AMD64ネイティブノードを追加します。言語やツールチェーンが明確に交差コンパイルへ対応している場合だけ、Macと交差コンパイルを組み合わせます。
Apple Siliconの構成候補を確認する場合は、VPSMACのMacノード一覧で利用可能な環境を確認し、実際のDockerfileで接続、公開、再起動まで試してください。地域や接続経路が要件になる場合は、東京のApple Siliconノードのように候補を絞り、CIからのSSH遅延と管理経路を検証します。
単一のLinuxクラウドサーバーだけではmacOS上のDocker実行環境やApple SiliconのARM64検証を代替できず、QEMUだけのMac構成ではAMD64のコンパイル負荷と互換性リスクが残ります。長期的に常時稼働するARM64 Builderが不足しているなら、VPSMACのApple SiliconリモートMacを週単位または月単位で試し、あなたのDockerfileでビルド、プッシュ、Manifest確認、再起動復旧まで合格させてから正式なCIノードへ加えるのが安全です。長期の固定負荷や物理デバイス接続が主目的なら自前機の方が適する場合もありますが、検証用の常駐Macや段階的なCI増設なら、先にレンタルで構成の妥当性を確かめられます。