Docker で M1/M2/M3 Mac ビルドのイメージが本番・CI で動かない・エラーになる:arm64/amd64 プラットフォーム不一致の解決法
公開日:2026-09-01/カテゴリ:Docker・開発環境・CI/CD・Apple Silicon/AnchorUp 技術ブログ
M1/M2/M3 Mac でビルドした Docker イメージが本番・CI で動かない症状
Apple Silicon(M1/M2/M3)の Mac を使っていて、こんな経験はありませんか?
- ローカルで
docker build && docker runすると問題なく動く - GitHub Actions にプッシュしたら CI が失敗する
- AWS ECS や Cloud Run、Fly.io にデプロイしたらコンテナが起動しない
このとき出ているエラーがこちら:
exec /bin/sh: exec format error
または:
WARNING: The requested image's platform (linux/arm64/v8) does not match
the detected host platform (linux/amd64/v2) and no specific platform was
requested
原因は1つ:Apple Silicon は arm64 アーキテクチャで、本番環境・CI は linux/amd64(x86_64)だから。
この記事では原因の仕組みから、実際の解決策(開発・CI・本番すべての設定)まで解説します。
なぜこの問題が起きるのか
CPU アーキテクチャが違う
| 環境 | アーキテクチャ |
|---|---|
| M1/M2/M3 Mac | arm64(aarch64) |
| Intel Mac | amd64(x86_64) |
| GitHub Actions(ubuntu-latest) | amd64 |
| AWS ECS(デフォルト) | amd64 |
| Google Cloud Run(デフォルト) | amd64 |
| Fly.io(デフォルト) | amd64 |
Docker はビルドしたマシンのアーキテクチャに合わせたバイナリを含むイメージを作ります。M1 Mac でビルドすると arm64 のバイナリが入ったイメージができます。このイメージを amd64 の環境で実行しようとすると、バイナリが実行できずに exec format error が発生します。
なぜローカルでは動くのか
Docker Desktop for Mac は QEMU エミュレーションを内蔵しており、arm64 マシン上でも amd64 イメージを(遅いですが)動かせます。そのため、手元では気づきません。
解決策1:docker build に --platform を指定する(最速)
ローカルでのビルドに --platform linux/amd64 を付けるだけで解決します。
# NG: プラットフォーム未指定(M1 Mac では arm64 イメージになる)
docker build -t myapp .
# OK: amd64 を明示指定
docker build --platform linux/amd64 -t myapp .
docker run でも同様に指定:
docker run --platform linux/amd64 myapp
QEMU エミュレーションが走るためローカルでの起動は少し遅くなりますが、CI・本番と同じ環境を手元で確認できます。
解決策2:Dockerfile に FROM --platform を書く
Dockerfile の先頭に --platform を固定することで、ビルドコマンドを打つ人が指定を忘れても常に amd64 になります。
# FROM の前に --platform を指定
FROM --platform=linux/amd64 node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
ただし、チームに Apple Silicon と Intel が混在していて将来的にマルチアーキテクチャ対応したい場合は後述の buildx 方式が柔軟です。
解決策3:docker buildx でマルチアーキテクチャビルド(推奨)
本番は amd64、ローカル開発は arm64 でネイティブ速度で動かしたい場合は、docker buildx でマルチプラットフォームイメージを作るのが最善です。
buildx のセットアップ
# ビルダーを作成して使用開始
docker buildx create --name mybuilder --use
# QEMU の設定(クロスプラットフォームビルドに必要)
docker run --privileged --rm tonistiigi/binfmt --install all
# ビルダーの確認
docker buildx inspect --bootstrap
マルチアーキテクチャビルド
# arm64 と amd64 の両方をビルドして Docker Hub にプッシュ
docker buildx build --platform linux/amd64,linux/arm64 -t yourname/myapp:latest --push .
--push を付けるとビルド後に自動でレジストリ(Docker Hub 等)にプッシュされます。この1つのイメージタグを使えば、amd64 の本番サーバーでも arm64 の M1 Mac でも最適なバイナリが自動選択されます。
GitHub Actions の設定
CI で毎回 QEMU エミュレーションのビルドが走ると遅いので、GitHub Actions では公式アクションを使います。
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: yourname/myapp:latest
cache-from: type=gha
cache-to: type=gha,mode=max
ポイント:
docker/setup-qemu-action: クロスコンパイルに必要な QEMU を設定docker/setup-buildx-action: buildx を有効化cache-from/cache-to: type=gha: GitHub Actions のキャッシュを使ってビルドを高速化
ネイティブモジュール(sharp、better-sqlite3)の落とし穴
sharp や better-sqlite3 など、C++ のネイティブアドオンを含む npm パッケージは特に注意が必要です。
よくある失敗
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci # ← ここで arm64 向けのバイナリがインストールされる
COPY . .
M1 Mac でビルドすると arm64 向けの .node ファイルがインストールされ、amd64 本番環境では動きません。
解決策:FROM に --platform を指定する
FROM --platform=linux/amd64 node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci # ← amd64 向けのバイナリがインストールされる
COPY . .
または buildx でビルドする場合、npm ci はクロスコンパイル環境で実行されるため、正しいアーキテクチャのバイナリが入ります。
docker-compose.yml での設定
docker-compose.yml で開発環境を管理している場合は platform キーを追加します。
# docker-compose.yml
services:
app:
build:
context: .
platform: linux/amd64 # 追加
ports:
- "3000:3000"
db:
image: postgres:16
platform: linux/amd64 # イメージ指定のサービスにも追加
environment:
POSTGRES_PASSWORD: password
症状・原因・対策の一覧
| 症状 | 原因 | 対策 |
|---|---|---|
exec format error |
arm64 バイナリを amd64 で実行 | --platform linux/amd64 を指定 |
| CI でコンテナが起動しない | M1 Mac でビルドした arm64 イメージ | Dockerfile に FROM --platform |
| ネイティブモジュールが動かない | アーキテクチャ違いの .node ファイル | --platform 指定で再 npm install |
| ローカルでは動くのに本番で落ちる | QEMU エミュレーションでローカル動作 | buildx マルチアーキテクチャビルド |
| arm64 イメージで本番が遅い | QEMU エミュレーション実行 | amd64 専用または Graviton 検討 |
まとめ
Apple Silicon Mac でビルドした Docker イメージが CI・本番で動かない原因は、arm64 と amd64 のアーキテクチャ不一致です。
推奨する対処の優先順位:
- 即効薬:
docker build --platform linux/amd64を追加する - チーム共有: Dockerfile に
FROM --platform=linux/amd64を書く - 本番運用:
docker buildxでマルチアーキテクチャイメージをビルドする - CI 最適化: GitHub Actions で
docker/setup-buildx-action+docker/build-push-actionを使う
本番環境が AWS Graviton(arm64)や M-series Mac に統一されるチームであれば、逆に全環境を arm64 に揃えることでエミュレーションを排除できます。環境が混在するチームは buildx のマルチアーキテクチャビルドが最もメンテナンスしやすい選択肢です。