M1 macでbuildしたコンテナがAmazon SageMaker Studioで動かなかったので対処した話
皆さんこんにちは。hotoke_nekoです。
本日は、M1 macでbuildコマンドで作ったコンテナが動かなかったのですが、どのように解決したのかをお伝えします。
先に結論
--platformオプションを省略した場合は、ビルドを実行する環境のOS/CPUアーキテクチャが自動的に指定されます。
したがってbuildコマンドに--platformオプションをつけて次のコマンドを実行します。
docker build . --platform amd64 -t <your container name>
エラー発生とその理由とは?
発生したエラー
standard_init_linux.go:228: exec user process caused: exec format error
このエラーが起きた理由はCPUのアーキテクチャが異なるためです。
CPUアーキテクチャが違う!
Dockerでは、コンテナという形でアプリケーションが実行されます。 それでは、どのOSを使ってアプリケーションが実行されるでしょうか?
正解は、仮想ブリッジというものを通してDockerが動いているホストOS上で実行する、です。
たとえばLinuxでは後方互換性が働いています。そのため、ホストOSでバージョンが新しいLinuxのOSを使っているとそれ以前のバージョンで作られたコンテナは動きます。(そのバージョンでしか実行できないような機能を持たせた場合は除きます。)
今回のエラーはコンテナ作成環境と実行環境では互換性がなかったので発生した、という事になります。
実際に確認したところ、ローカル環境は次のようになりました。
$ uname -m arm64
今回自分が使用したインスタンス('ml.c4.2xlarge'インスタンス)のCPUアーキテクチャはamd系になります。詳細についてはこちらをご参照ください。
つまり今回のエラーは、Amazon SageMaker Studioではamdのアーキテクチャで、コンテナを作成したM1 macとCPUアーキテクチャが異なるため発生したのです。
ちなみに、Intelが入っているmacではエラーが出ないそうです。(PCお持ちの方に確認しました。)
CPUアーキテクチャの違いを吸収するには?
コンテナを実行する環境に合わせる必要があります。そこで、buildコマンドでCPUアーキテクチャの違いを吸収します。
今回SamgeMaker Studioでコンテナを動かそうとしているインスタンスが'ml.c4.2xlarge'というもので、amdである事は前述しました。
そこで、ローカルでのbuildコマンドの際に、コンテナ実行環境のCPUアーキテクチャに合わせて--platformオプションをつけて実行しましょう。
docker build . --platform amd64 -t <your container name>
関連事項
ローカルであればVagrantを使ってその上でDokcerを実行すると、他のCPUアーキテクチャで作られたコンテナの実行時エラー回避が可能な場合もあります。
また、さまざまなCPUアーキテクチャに対応したいという場合はbuiltxというコマンドが使えますのでぜひご確認ください。
終わりに
M1 macを使ってbuildコマンドをした時に発生したエラーを回避する方法について解説してみました。
今回のように、ホストOSが分かっている場合でホストOSが変更できないのであれば、それに合わせてコンテナビルド時にCPUアーキテクチャを指定する必要があります。
もし同じエラーが発生した時に、皆さんのお役に立てれば幸いです。
今回はここまで。
それでは、また!