LoginSignup
7
3

M2 Mac で amd64 アーキテクチャの Phoenix コンテナをビルドする

Last updated at Posted at 2023-08-29

はじめに

M2 Mac (Apple silicon: arm64 = aarc64 アーキテクチャ) で amd64 アーキテクチャ用のコンテナをビルドしようとしたところ、エラーが発生したので、その内容と対策方法を残しておきます

同じ Apple silicon である M1 Mac でも同様だと思われます

エラー内容

以前記事で紹介した AWS Copilot による Phoenix のデプロイを実行していました

Dockerfile は以下の内容です

FROM elixir:1.15.4

# hadolint ignore=DL3008
RUN apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y inotify-tools \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN mix local.rebar --force

COPY ./app /app

WORKDIR /app

RUN mix deps.get
RUN mix compile.phoenix

EXPOSE 4000

CMD ["mix", "phx.server"]

以前はいわゆる Intel Mac だったので、ローカルもデプロイ先も同じ amd64 = x86_64 アーキテクチャでしたが、先日導入した M2 Mac で同じ手順を実行したところ、コンテナのビルド中(copilot svc deploy 実行時)に以下のようなエラーが発生しました

...
 => ERROR [phoenix 6/7] RUN mix deps.get                                                                                      2.9s
------                                                                                                                             
 > [phoenix 6/7] RUN mix deps.get:
2.608 Segmentation fault (core dumped)
------
failed to solve: process "/bin/sh -c mix deps.get" did not complete successfully: exit code: 139

何度かやっていると、以下の内容になることもありました

...
 => ERROR [phoenix 6/7] RUN mix deps.get                                                                                      3.2s
------                                                                                                                             
 > [phoenix 6/7] RUN mix deps.get:                                                                                                 
2.417 no next heap size found: 2305842975249271902, offset 0                                                                       
2.422 
2.422 Crash dump is being written to: erl_crash.dump...done
2.924 Aborted (core dumped)
------
failed to solve: process "/bin/sh -c mix deps.get" did not complete successfully: exit code: 134

同じ定義で Intel Mac でデプロイすると上手くいったので、これは明らかにアーキテクチャの違いによるものです

エラーの原因

AWS Copilot の manifest.yml は以下のようになっていました

...
cpu: 256
memory: 512
platform: linux/x86_64  # ここで x86_64 アーキテクチャの指定
count: 1
exec: true
network:
  connect: true
...

この場合、 AWS Copilot の内部的な処理で以下のような Docker のビルドコマンドが実行されています

$ docker build \
    -t xxx.dkr.ecr.ap-northeast-1.amazonaws.com/apb/xxx-svc:latest \
    --platform linux/x86_64 \
    --label com.aws.copilot.image.builder=copilot-cli \
    --label com.aws.copilot.image.container.name=xxx-svc \
    --label com.aws.copilot.image.version=v1.29.1 \
    <カレントディレクトリー>

--platform linux/x86_64 で x86_64 アーキテクチャを指定していますね

Dockerfile の FROM で指定している元イメージは elixir:1.15.4 です

スクリーンショット 2023-08-25 14.38.17.png

OS/ARCH のところに複数のアーキテクチャが入っており、このイメージがマルチアークテクチャであることが分かります

マルチアーキテクチャの場合、 --platform を指定しなければ、ビルドしている環境に合ったアーキテクチャが自動的に選択されます

M1 Mac や M2 Mac であればデフォルトで linux/arm64/v8 が使われます

今回のように --platform linux/x86_64 を指定すると linux/x86_64 が選択されます

それでも基本的には問題なくビルドが進みます

ただし、 mix deps.get 実行時にこのアーキテクチャの差異によってエラーが発生したものと思われます

エラーの対応策

Elixir Forum に対応策がありました

Dockerfile の mix deps.get よりも前に以下のコードを追加することでエラーが発生しなくなります

ENV ERL_FLAGS="+JPperf true"

Erlang のドキュメントに JPperf に関する情報が記載されていますが、正直なぜこれで上手くいくのかはよく分かっていません

分かる方はコメントいただけると助かります

まとめ

例えば Fly.io のようにコンテナのビルドをクラウド上で実行する場合、このような問題は発生しません

AWS Copilot を使う場合でも、まだ試していませんが Pipeline などを使えば大丈夫そうです

今回はローカルでも対策を取ることができましたが、やはりアーキテクチャの違いによる問題は今後も出てくると思うので、まだしばらくは Intel Mac も手元に必要そうですね

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3