はじめに
M1/M2/M3/M4などのApple Silicon(arm64アーキテクチャ)のMacからDockerイメージをビルドし、Amazon ECRへプッシュしてECSやApp Runner等で動かそうとした際、コンテナが即座にクラッシュして起動しないという問題に直面しました。
備忘録を兼ねて、原因と解決策をまとめます。
- 原因:マルチプラットフォームの罠(Exec format error)
AWS側のCloudWatch Logsなどを確認した際、以下のようなエラーが出力されている場合、原因はCPUアーキテクチャの不一致です。
text
standard_init_linux.go:228: exec user process caused: exec format error
ecsの起動ログやコードデプロイ時の初期ecsのイベントログにarm64というエラーと共にcloudwatchには、formatエラーが一件だけ出力されました。
コードは注意してご使用ください。
なぜ起きるのか?
• あなたのMac: arm64 (Apple Silicon)
• AWSのデプロイ先(デフォルト): x86_64 (Intel/AMD系)
通常の docker build コマンドは、ビルドを実行しているマシンのCPU(今回はarm64)に合わせてイメージを作成します。そのため、「x86/arm64両方をビルドしたつもり」であっても、適切なオプションやツールを使わないと、AWS(x86_64環境)側で「読めない形式のバイナリ」と判定されて起動に失敗します。
- 解決策
AWS側の実行環境に合わせて、適切な方法でビルド・プッシュを行います。
解決策A:AWS側が x86_64(一般的な環境)の場合
通常の docker build に、ターゲットとなるプラットフォームを明示する --platform linux/amd64 オプションを付与してリビルドします。
bash
1. x86_64(amd64)向けに明示してビルド
docker build --platform linux/amd64 -t <あなたのECRリポジトリURI>:latest .
2. ECRへプッシュ
docker push <あなたのECRリポジトリURI>:latest
コードは注意してご使用ください。
解決策B:x86_64 / arm64 の両方に対応させたい場合
AWS側(ECS Fargate等)の設定でARM(Graviton)を使う可能性があったり、双方に対応した「マルチプラットフォームイメージ」を作りたい場合は、docker buildx を使用します。
bash
1. buildxのビルダーを作成して切り替え(初回のみ)
docker buildx create --use
2. 両アーキテクチャを同時にビルドし、直接ECRにプッシュする
※buildxで複数指定する場合はローカル保存ができないため、直接 --push します
docker buildx build --platform linux/amd64,linux/arm64 -t <あなたのECRリポジトリURI>:latest --push .
コードは注意してご使用ください。
- それでも直らない場合のチェックポイント
上記を行っても起動しない場合は、Dockerfile内のベースイメージやライブラリが原因の可能性があります。
• ベースイメージが固定されていないか?
FROM python:3.11 などの公式イメージはマルチプラットフォーム対応ですが、独自にビルドされたイメージや一部のマイナーなベースイメージは x86_64 でしか動かないバイナリが含まれていることがあります。
• FastAPI依存ライブラリの拡張モジュール
FastAPI(PydanticやUvicornなど)の内部でC言語等を使って高速化されているライブラリが、ビルド時にターゲット(linux/amd64)用に正しくコンパイルされているか確認してください(解決策AやBの手順を踏めば自動的に対応ツールが切り替わります)。
まとめ
MシリーズMacからAWS環境へコンテナをデプロイする際は、常に --platform linux/amd64 を意識するか、docker buildx を活用するのが安全です。
この記事がどなたかの参考になれば幸いです。