Can't compile Elixir/Phoenix API in Docker build step

I have an Elixir/Phoenix API (running Elixir 1.14) that I’m trying to containerize for deployment and it’s giving me a major headache.

I’m on an M1 macbook, but I’m building the image to deploy to AWS ECS. It will specifically fail on the mix deps.compile line with this error:

 => => # Error while loading project :decimal at /user/app/deps/decimal
 => => # qemu: uncaught target signal 11 (Segmentation fault) - core dumped

I’ve tried manually including the decimal library, updating it, reinstalling it, changing the Elixir version, the OTP version, the architecture but no luck. Could someone point me in the right direction?

Here’s my Dockerfile.

# Use the official Elixir 1.14 base image
FROM --platform=linux/x86_64 elixir:1.14-otp-25-alpine

# Install any necessary dependencies
RUN apk add build-base
RUN apk add --update make

# Set the environment variables for the application
ENV MIX_ENV=prod \
  APP_NAME=my_app \
  APP_VERSION=0.1.0 \
  PORT=80

EXPOSE 80

# Create the application directory and copy the application code
WORKDIR /user/app

COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

COPY . .

# Install the application dependencies
RUN mix local.hex --force && \
  mix local.rebar --force && \
  mix deps.get --only prod

# Compile the application code
RUN mix deps.compile


# Set the entry point script for the container
ENTRYPOINT ["docker-entrypoint.sh"]
```

One common cause of segmentation fault is running out of memory - check the Docker and qemu settings, you may need to allocate the container more RAM.

1 Like

I just cranked up the RAM, but no change.

I’d be surprised if it’s a memory issue as it’s saying it can’t find a dependency :confused:

I don’t think this is possible.

So to be more precise, to deploy straight from a host to a separate target, the Erlang Runtime System (ERTS), and any native dependencies (NIFs), must be compiled for the same target triple. If you are building on a MacBook (x86_64-apple-darwin ) and trying to deploy to a typical Ubuntu machine (x86_64-unknown-linux-gnu ), the release will not work. Instead you should build the release on a x86_64-unknown-linux-gnu host. As we will see, this can be done in multiple ways, such as releasing on the target itself, or by using virtual machines or containers, usually as part of your release pipeline.

https://hexdocs.pm/mix/1.15.2/Mix.Tasks.Release.html

From what I remember this problem surfaced multiple times on this forum, the thing is about the JIT optimization of OTP (JIT was introduced from OTP-24) not working with qemu, so it is not to compile OTP using a emulator.

I would suggest to use a shared runner, or if you are willing to spend a few bucks a custom runner on gitlab and run the docker build there. Or from what I know ECS now offers ARM instances, theoretically should be compatible straight with the build from M1.

1 Like

Thank you all for the help!!

Setting up a CD pipeline was the solution, and it worked without issue.

I created a GitHub action that ran the project compilation for me and pushed it to my cluster. Worked first time!

1 Like

My Phoenix Docker projects targeting x86_64/amd64 are all building great on my M2 Mac once I add these lines to my Dockerfile right after ENV MIX_ENV="prod":

# Workaround QEMU JIT issue building AMD64 on ARM64
ENV ERL_FLAGS="+JPperf true"

I think this only disables JIT during the build process. When the release runs in production performance is not affected.

2 Likes