M1macでのDockerfileのBuildで鬼沼った話
今回は、DockerfileをBuildしECRにプッシュ。その後ECSでタスク実行という一般的な流れで沼った話です。
standard_init_linux.go:228: exec user process caused: exec format errorになる
M1macでビルドしたimageをECRにプッシュし、ECSでタスク実行すると上記のようなエラーが出ました。
docker inspect [imagename]:latest
で、作成したimageの中身を確認すると、たしかに"Architecture"が"arm64"になってるんですよね。
この辺は、DevelopersIOの「Dockerのマルチアーキテクチャイメージについて調べてみた」という記事があるので、そちらを読んでいただければ理解できると思います。
要するに、ビルドしたのはarm64のパソコンでイメージもarm64用なのに、実行しているのはx86_64なのでアーキテクチャが違いますよーとエラーが出てるわけですね。
解決策は大きく分けて2つです。
- 同じアーキテクチャのパソコン(サーバー)でビルドする
- 実行する環境を合わせる
同じアーキテクチャのパソコン(サーバー)でビルドする
おなじアーキテクチャのPCでビルドすれば問題なく実行できます。
例えばlinux/x86_64環境のEC2上に、Dokerfileなどの必要なファイルをアップし、そこでビルド。
ECRにプッシュするという方法です。この方法であればアーキテクチャの差異は生まれません。
また、buildxでマルチアーキテクチャに対応した形にビルドする方法もあります。その際は、ローカルに保存してもarm64に対応したイメージしか残らないので、doker hubにプッシュするようにしてビルドしましょう。
Doker hub上のイメージをlinux/x86_64環境のEC2でpullした上で、ECRにプッシュすることでエラーなく実行できるようになります。
他には、使用するファイルをGithubにアップロードし、AWSのcodebuildを使ってビルドする方法もあります。
最適なのは最後に紹介した、codebuildでビルドする方法でしょう。実行する環境を合わせる
私は今回はこの方法で解決しました。
最も簡単だったからです。
最初は気づかなかったのですが、ECSのコンソール画面の左上には「新しい ECS エクスペリエンス」なる箇所があります。こちらをクリックすると、コンソール画面が変わり、タスク定義を作成する際にarm64が選べるようになるのです。
こちらでアーキテクチャをARM64にすることで該当するエラーは解決できます。
Discussion