Apple Silicon でビルドした Docker イメージを Cloud Run にデプロイする
June 8, 2023
私はまだ Intel Mac を使っているのですが、別の Apple Silicon Mac で作業したときに遭遇したことです。
ローカルでビルドした Docker イメージを Cloud Run にあげて動かしたところ、次のエラーがでて起動できませんでした。これは Cloud Run のログに出力されたメッセージです。
terminated: Application failed to start: Failed to create init process: failed to load /usr/local/bin/docker-entrypoint.sh: exec format error
原因と解決策はこの Stack Overflow に書いてありました。
- Cloud Run: “Failed to start” - Stack Overflow
- https://stackoverflow.com/questions/66127933/cloud-run-failed-to-start-and-then-listen-on-the-port-defined-by-the-port-envi#answer-68766137
結論だけ書くと、イメージをビルドする際のコマンドを以下のようにすれば解消するはずです。
docker buildx build ./ --platform linux/amd64 -t TAG_NAME
以降では、原因とその解決策について詳しく見ていきたいと思います。
説明 #
エラーとなる原因は、Apple Silicon で ビルドした Docker イメージの形式を Cloud Run がサポートしていないためです。
Cloud Run のドキュメントによると #
Cloud Run のドキュメントには次のように書いてあります。
Executables in the container image must be compiled for Linux 64-bit. Cloud Run specifically supports the Linux x86_64 ABI format.
Cloud Run で動かすためには Linux 64 ビット用にコンパイルする必要があります、と説明されています。
CPU の違い #
CPU に何かを命令するときは、その CPU の「命令セット」に従って命令を実行します。つまり命令セットは機械語(マシン語)の仕様のことです。
当然、命令セットが異なる CPU に対してはその命令セットに基づいて命令を実行する必要があります。
Intel Mac の CPU は Intel のアーキテクチャ、Apple Silicon Mac の CPU は ARM のアーキテクチャです。そして両者の「命令セットアーキテクチャ(ISA, instruction set architecture)」は異なっています。
あなたの Mac でターミナルを開き、次のコマンドを実行してみてください。
uname -m
私の Intel Mac では x86_64
と表示されます。Apple Silicon Mac の方であれば arm64
と表示されたのではないでしょうか。
docker build について #
docker build デフォルトでは実行する端末の CPU アーキテクチャでビルドします。
次のコマンドを実行したとき、あなたの Mac が Apple Silicon であれば arm64
向けの Docker イメージを作成します。
docker build ./ TAG_NAME
そしてこれを Cloud Run にデプロイすると冒頭のエラーになります。
もう理由はお分かりかと思いますが、Cloud Run では arm64
向けにビルドされた Docker コンテナは実行できないからです。
x86_64
向けに Docker イメージをビルドする
#
あなたの Mac が Apple Silicon だとしても Cloud Run で実行するためには x86_64
向けに Docker イメージをビルドする必要があります。
そのためには、docker build のコマンドを次のように実行しましょう。
docker buildx build ./ --platform linux/amd64 -t TAG_NAME
- 参考:上記の docker コマンドに関する公式ドキュメントの該当部分は以下です。
- Set the target platforms for the build | docker buildx build | Docker Documentation
- https://docs.docker.com/engine/reference/commandline/buildx_build/#platform
上記は linux/amd64
のアーキテクチャ向けにビルドしています。
x86_64
でなくて amd64
なの?と思うかもしれませんが、両者は同じものを指しています。これは次の記事がわかりやすいです。
- 「x86-64」「x64」「AMD64」これらは何が違うのか?
- https://onoredekaiketsu.com/x86-64-x64-amd64-what-is-the-difference-between-these/
ということで、上記でビルドしたイメージを Cloud Run にデプロイしてみてください。エラーが発生せず上手く動いたのではないでしょうか?
あるいは Dockerfile 内で指定することもできる #
冒頭にリンクを貼った Stack Overflow の記事で紹介されている方法は、docker build コマンドに --platform
オプションを付与するものでしたが、それを Dockerfile に記述することもできます。
Dockerfile の FROM にて –platform を指定します。(なおここでは例として node のベースイメージを使用しました。)
# 変更前
FROM node:18-bullseye-slim
# 変更後
FROM --platform=linux/amd64 node:18-bullseye-slim