Search code examples
amazon-ec2erlangelixirerlang-otpelixir-mix

mix release on Amazon Linux 2


Goal: to be able to run a phoenix, mix release in an ec2 instance (this machine: https://hub.docker.com/_/amazonlinux/)

Problem: Running my release produces the following error:

/my_app/erts-11.0.3/bin/beam.smp: /lib64/libtinfo.so.6: no version information available (required by /my_app/erts-11.0.3/bin/beam.smp)
2020-09-08 13:17:33.469328
    args: [load_failed,"Failed to load NIF library /my_app/lib/crypto-4.7/priv/lib/crypto: 'libcrypto.so.1.1: cannot open shared object file: No such file or directory'","OpenSSL might not    format:     label:  be installed on this system.\n"]
"Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n~s"
{error_logger,error_msg}

but I have openssl installed in each scenario (OpenSSL 1.0.2k-fips 26 Jan 2017).

Setup:

I create a new phoenix project with:

yes | mix phx.new my_app --no-webpack --no-ecto --no-dashboard --no-gettext
cd my_app

and uncomment the config :my_app, MyAppWeb.Endpoint, server: true line in config/prod.secret.exs to start the server when running the app.

I create the following Dockerfile to build my project:

FROM debian:buster

# Install essential build packages
RUN apt-get update 
RUN apt-get install -y wget git locales curl gnupg-agent

# Set locale
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=en_US.UTF-8
ENV LANG en_US.UTF-8

ENV HOME=/opt/app

WORKDIR /opt/app

# Install erlang and elixir
RUN wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
RUN dpkg -i erlang-solutions_2.0_all.deb
RUN apt-get update
RUN apt-get install -y esl-erlang
RUN apt-get install -y elixir

# Install hex and rebar
RUN mix do local.hex --force, local.rebar --force

# Install phoenix
RUN mix archive.install hex phx_new 1.5.4 --force

COPY mix.exs mix.lock ./
COPY config config
COPY priv priv
COPY lib lib

RUN mix deps.get

ENV SECRET_KEY_BASE='secretExampleQrzdplBPdbHHhr2bpELjiGVGVqmjvFl2JEXdkyla8l6+b2CCcvs'
ENV MIX_ENV=prod

RUN mix phx.digest
RUN mix compile
RUN mix release

CMD ["_build/prod/rel/my_app/bin/my_app", "start"]

and build the image with:

docker build . -t my_app

We can check that everything is running as expected with:

docker run -p 4000:4000 -i my_app:latest

and visiting localhost:4000.

I copy the _build/prod/rel/my_app directory from the built docker container (as this is all I'll be transferring across to my ec2 instance).

# list all containers
docker container ls -a
# locate the container with image tag: my_app:latest. It should look like:
# f9c46df97e55        my_app:latest         "_build/prod/rel/my_…"
# note the container_id, and copy across the build release
docker cp f9c46df97e55:/opt/app/_build/prod/rel/my_app .

We create an instance.Dockerfile to run the commands of our ec2 instance:

FROM amazonlinux:latest

COPY my_app my_app

CMD ["my_app/bin/my_app", "start"]

and run it:

docker build . -f instance.Dockerfile -t my_app_instance && docker run -p 4000:4000 -i my_app_instance:latest

This fails to run, with the error:

[load_failed,"Failed to 2020-09-08 13:27:49.980715
    args: load NIF library /my_app/lib/crypto-4.7/priv/lib/crypt    format:     label: 2020-09-08 13:27:49.981847 supervisor_report   o: 'libcrypto.so.1.1: cannot open shared object file: No such file or directory'","OpenSSL might not be installed on this system.\n"]
"Unable to load crypto library. Failed with error:~n\"~p, ~s\"~n~s"
{error_logger,error_msg}

Note:

I am able to replicate the error on a debian:buster machine with the above docker build ... && docker run ... command, but with this instance.Dockerfile:

FROM debian:buster

RUN apt-get update 
RUN apt-get install -y locales

# Set locale
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=en_US.UTF-8
ENV LANG en_US.UTF-8

COPY my_app my_app

CMD ["my_app/bin/my_app", "start"]

and fix the error by changing: RUN apt-get install -y locales to RUN apt-get install -y locales curl.

I have tried yum install curl and yum install openssl on the amazonlinux:latest machine, but still experience the same error.

Question:

Where should I look to make progress on this? It seems to be an erlang/otp requirement issue, but the above is hardly a sscce, so difficult to raise.

I have struggled with finding what crypto or openssl library the apt-get curl package installs which causes the error to be fixed.

Any pointers to a particular forum to ask for help, or what to try next would be greatly appreciated.

Thanks in advance for the help.


Solution

  • Thanks to the suggestion to build it on CentOs from @VenkatakumarSrinivasan,

    I managed to get it working on an amazonlinux machine with the following Dockerfiles.

    Building the release:

    FROM centos:7
    
    RUN yum update -y
    RUN yum clean -y all
    
    RUN echo 'LC_ALL="en_US.UTF-8"' >> /etc/locale.conf
    ENV LC_ALL="en_US.UTF-8"
    
    RUN yum install -y epel-release
    RUN yum install -y gcc gcc-c++ glibc-devel make ncurses-devel openssl-devel \
                       autoconf java-1.8.0-openjdk-devel git wget wxBase.x86_64
    
    WORKDIR /opt
    
    RUN wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm
    RUN rpm -Uvh erlang-solutions-1.0-1.noarch.rpm
    RUN yum update -y
    RUN yum install -y erlang
    
    WORKDIR /opt/elixir
    
    RUN git clone https://github.com/elixir-lang/elixir.git /opt/elixir
    
    RUN make clean test
    
    ENV PATH=/opt/elixir/bin:${PATH}
    
    RUN mix do local.hex --force, local.rebar --force
    RUN mix archive.install hex phx_new 1.5.4 --force
    
    WORKDIR /opt/app
    
    COPY mix.exs mix.lock ./
    COPY config config
    COPY priv priv
    COPY lib lib
    
    RUN mix deps.get
    
    ENV SECRET_KEY_BASE='secretExampleQrzdplBPdbHHhr2bpELjiGVGVqmjvFl2JEXdkyla8l6+b2CCcvs'
    ENV MIX_ENV=prod
    
    RUN mix phx.digest
    RUN mix compile
    RUN mix release
    
    CMD ["_build/prod/rel/my_app/bin/my_app", "start"]
    

    Running the release:

    FROM amazonlinux:latest
    
    RUN yum -y update 
    
    ENV LANG="en_US.UTF-8"
    ENV LC_ALL="en_US.UTF-8"
    
    RUN ln -s /usr/lib64/libtinfo.so.{6,5}
    
    COPY my_app my_app
    
    CMD ["my_app/bin/my_app", "start"]
    

    I'm not sure if this is a satisfying solution though, I'm open to a more elegant solution.