🐳
MBP移行直後に踏んだdocker buildのエラー
要約
新しいMBPに移行してdockerイメージをbuildしたところ、 これまで正常に動いていたCloud Runのジョブが exec format error
となって処理が失敗しました。
buildのオプションとして--platform linux/amd64
を指定してもダメでした。
DOCKER_BUILDKIT=0
を指定して BuildKit を無効にしてビルドしたところ、諸々インストールされて依存関係が改善されたらしくうまくいきました。
Docker BuildKitとマルチプラットフォーム対応についての教訓
Dockerを使えば、異なるCPUプラットフォーム(x86_64 と arm64 など)へ対応するイメージをビルドできます。しかし、一部の環境ではマルチプラットフォームビルドにより、以下のような問題が起こることがあります。
- Cloud Run で
exec format error
が発生して起動しない - QEMUエミュレーションが正しく機能せずキャッシュ不整合が起きる
本記事では、私が遭遇した事例をもとに、解決策や注意点をまとめました。
背景
-
ベースイメージ:
python:3.11-slim
-
Docker Buildx:
--platform linux/amd64,linux/arm64
でマルチプラットフォームビルド - 環境: M4 Mac / Orbstack
- 目的: Cloud Run 上でコンテナジョブを実行
-
遭遇したエラー:
exec format error
アーキテクチャ図 (簡易版)
以下は、マルチプラットフォームビルドを行う際の概念図です。
┌────────────────────┐
│ Host (ARM/M4) │
│ │
│ Docker BuildKit │
└────────┬───────────┘
│
│(buildx build)
▼
┌─────────────────────┐
│ Docker Registry │
│ (Artifact Registry) │
│ ├─ amd64 Image │
│ └─ arm64 Image │
└────────┬────────────┘
│
│(pull)
▼
┌───────────────────┐
│ Cloud Run │
│ (linux/amd64) │
│ │
└───────────────────┘
-
ビルドプロセス: M1ホスト上で
docker buildx build --platform=...
を実行すると、BuildKit + QEMU がエミュレーションを通じて amd64 / arm64 両方のイメージを構築。 - レジストリへプッシュ: それぞれのイメージが1つのマニフェスト(マルチプラットフォーム対応)としてRegistryに登録される。
-
実行環境 (例: Cloud Run): 必要に応じて適切なアーキテクチャのイメージをプルして実行。ただし、Cloud Run は
linux/amd64
のみ対応なので、amd64
イメージが正しく生成されていないとエラーになる。
試した対策と学び
-
キャッシュを破棄してクリーンビルド
-
docker buildx prune --all
などでキャッシュ削除し、--no-cache
付きで再ビルド。 - キャッシュの不整合が原因で、過去の不完全なバイナリが再利用されるのを防ぐ。
-
-
DOCKER_BUILDKIT=0
で依存を再インストール- 一度従来のビルドを使うことで、全モジュールが再インストールされ、キャッシュがリセットされる。
- その後、
docker buildx build
に戻しても問題が解消することがある。
-
FROM --platform=linux/amd64 python:3.11-slim
の明示化- ベースイメージを amd64 に固定してビルドし、ターゲットが確実に amd64 になるようにする。
- 複雑なアプリでは arm64 版とあわせてビルドしたい場合、プラットフォームごとにマルチステージ構成を検討。
-
Orbstack を避け、Docker Desktop標準環境で再検証
- Orbstack など特定の仮想化レイヤが原因の場合、公式 Docker Desktop で同手順を試すと成功するケースがある。
-
マニフェストの確認
-
docker manifest inspect <イメージ>
でarchitecture
がamd64
/arm64
の2つが含まれているか確認。
-
-
エントリポイントやファイル構成の再点検
-
exec format error
はアーキテクチャ以外にも、CMD
やENTRYPOINT
が存在しないファイルを指している、権限がない、などで発生することがある。 - 単純なケアレスミスがないか要チェック。
-
補足リンク
まとめ
- キャッシュ管理 と 依存インストールの安定化 がとても重要
- マルチプラットフォームビルドは便利だが、環境ごとの癖がある
- まずは単一アーキテクチャで正常動作させ、次にマルチプラットフォーム化を試す
- エラーが続く場合は BuildKit をオフにしてビルドし、問題を切り分け
このアプローチで何とか exec format error
問題を解決し、Cloud Run でのジョブ実行が成功しました。 もし同様の現象に悩んでいる方のヒントになれば幸いです。
Discussion