動かない時
M1/M2 Mac で amd64 イメージが動かない
Apple Silicon で `exec format error` や `qemu: uncaught target signal` が出るときの切り分けと、`--platform`・`buildx`・`qemu-user-static` による対処。
症状
- Apple Silicon(M1/M2/M3)の Mac で
docker run some/imageするとexec /entrypoint.sh: exec format errorが出る - 起動は通るが途中で
qemu: uncaught target signal 11 (Segmentation fault)でクラッシュする docker compose upでは動くのにdocker runだと落ちる(または逆)- GitHub Container Registry からプルした古めの社内イメージだけ動かない
原因
Apple Silicon の CPU は arm64 ですが、配布されているコンテナイメージの多くは依然として amd64 のみ、あるいはマルチアーキ対応でも arm64 バリアントの品質が低い場合があります。
exec format error: amd64 のみのイメージを arm64 の Docker でそのまま実行しようとした。エミュレータ(QEMU)が挿されていないと即死するqemu: uncaught target signal: エミュレータ経由で amd64 バイナリを動かしているが、QEMU が特定の命令(AVX 命令や syscall)を正しく翻訳できずクラッシュ。Java や Node.js の JIT、ネイティブ拡張つきの Python パッケージで起きやすい- マルチアーキの落とし穴: レジストリ側のマニフェストリストが壊れている / arm64 イメージが amd64 のバイナリを含んでしまっている社内ビルドで誤動作
確認コマンド
bash
# ホストのアーキと Docker のデフォルトプラットフォーム
uname -m # arm64
docker info | grep -i arch
# イメージがどのアーキに対応しているか(マニフェストリスト)
docker buildx imagetools inspect some/image:tag
# pull したローカルイメージのアーキ
docker image inspect some/image:tag --format '{{.Architecture}} {{.Os}} {{.Variant}}'
# 実行時のプロセスから見える arch(QEMU で動いているなら x86_64 と返る)
docker run --rm some/image:tag uname -m
# QEMU エミュレータが登録されているか
docker run --rm --privileged tonistiigi/binfmt
# 出力の "emulators" に qemu-x86_64 等が含まれているか確認解決策
- まず arm64 ネイティブのタグを探す:
docker buildx imagetools inspectでマニフェストにlinux/arm64があるかを確認。公式イメージ(node,python,postgres等)は大半がマルチアーキ対応済み。あるならそれを使うのが最速・最安定 - 明示的に
--platform=linux/amd64を指定してエミュレーション実行: 社内イメージなどで arm64 ビルドがない場合。ただし性能は落ち、QEMU 起因のバグにはまるリスクありdocker run --platform=linux/amd64 some/image:tag - QEMU エミュレータを登録する: Docker Desktop for Mac には同梱されているが、初回のみ
binfmt経由で明示登録が必要なことがあるdocker run --privileged --rm tonistiigi/binfmt --install all - 自分でビルドするなら
buildxでマルチアーキを一度に作る: CI でも使えてローカルと同じ成果物になるdocker buildx create --use docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/you/app:v1 --push . - Compose の
platform:を書く: チーム内で M1/Intel が混在しているときは各サービスにplatform: linux/amd64(またはlinux/arm64)を明記し、環境差を封じる - QEMU で動かない JIT 問題の回避策: Node.js なら
NODE_OPTIONS=--jitless、Java なら-XX:-UseCompilerで JIT を切ると起動する場合がある(根本解決ではなく暫定対応)
