Docker を使って開発していると、ビルドしたコンテナを実行した際に次のようなエラーが表示されることがあります。
standard_init_linux.go:228: exec user process caused: exec format error
初めて見ると「何が壊れたのか?」と焦るエラーですが、実はこれは CPUアーキテクチャの不一致 に起因するケースがほとんどです。特に、Apple Silicon (M1/M2) や Raspberry Pi など ARM 環境で x86_64 用に作られた Docker イメージを動かすと発生します。
この記事では、原因と解決策、実際の回避例をわかりやすく解説します。
1. エラーが発生する背景と原因
Docker イメージはビルド時に対象アーキテクチャを基に作成されます。たとえば、linux/amd64
(x86_64)向けのイメージを Apple Silicon Mac (arm64) 上でそのまま実行すると、コンテナの ENTRYPOINT で実行されるバイナリが ARM CPU では実行できず、exec format error
になります。
docker run my-x86-image
# => standard_init_linux.go:228: exec user process caused: exec format error
つまり、イメージのアーキテクチャとホスト環境が一致していないのが根本原因です。
2. よくあるケースと再現例
特に次のケースでよく発生します。
- M1/M2 Mac で x86 用のイメージを動かしたとき
- Raspberry Pi (arm/v7) で amd64 の公式イメージを pull したとき
- マルチステージビルドで一部のステージだけアーキテクチャが異なるバイナリを含んでいるとき
再現コード例:
FROM ubuntu:20.04
COPY ./hello /usr/local/bin/hello
ENTRYPOINT ["hello"]
ここで hello
バイナリが x86_64 用にビルドされたもので、arm64 ホスト上で実行するとエラーになります。
3. 対処法1: –platform オプションを明示する
Docker Desktop は QEMU を使ったエミュレーションをサポートしているため、実行時に –platform オプションを指定すれば動作します。
docker run --platform=linux/amd64 my-x86-image
ビルド時にも同様に指定可能です。
docker buildx build --platform=linux/amd64 -t my-x86-image .
ただし、エミュレーションはパフォーマンスが低下するため、本番環境では避けるべきです。
4. 対処法2: マルチアーキテクチャイメージをビルドする
最も推奨される方法は マルチアーキテクチャ対応イメージをビルドすること です。Docker Buildx を使うと、複数アーキテクチャ向けのイメージを同時にビルドできます。
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t my-multiarch-image \
--push .
これにより、Docker Hub などにマルチアーキテクチャイメージが公開され、実行環境に応じて自動的に適切なイメージが pull されます。
5. 実運用での落とし穴とベストプラクティス
- CI/CD 環境でのビルドアーキテクチャ統一
GitHub Actions などではランナーが amd64 の場合が多く、ローカル (arm64) で動くバイナリを混在させると再現しない問題が発生します。docker buildx create --use
を CI でも設定して、マルチアーキテクチャビルドを常に実行すると安心です。 - バイナリを含む場合は cross-compilation を明示
Go や Rust でバイナリをビルドする場合、環境変数GOARCH=amd64
やCARGO_BUILD_TARGET
を設定してアーキテクチャを固定しましょう。 - 軽量化とキャッシュ戦略
マルチアーキテクチャビルドは時間がかかるため、--cache-from
オプションを活用してビルドキャッシュを再利用すると効率的です。
6. まとめ
Docker で「exec format error」が出る原因は、ほとんどの場合 イメージのアーキテクチャとホストの不一致 です。開発中は --platform
オプションで回避し、本番環境や CI/CD では マルチアーキテクチャビルド を採用するのがベストプラクティスです。特に M1/M2 Mac や Raspberry Pi のように ARM 環境を使う場合は、意識的にアーキテクチャを合わせる習慣をつけましょう。
参考
- Docker Buildx [https://docs.docker.com/buildx/working-with-buildx/]
- Multi-Platform Images [https://docs.docker.com/build/building/multi-platform/]
- QEMU User Emulation [https://docs.docker.com/desktop/multi-arch/]