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"]
```
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.
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.