Deployment in docker: where does elixir look for shared libraries?

I am getting errors regarding shared libraries in my Debian docker container:

Error loading shared library libncursesw.so.6: No such file or directory (needed by /app/erts-12.2.1/bin/beam.smp)
Error loading shared library libz.so.1: No such file or directory (needed by /app/erts-12.2.1/bin/beam.smp)
Error loading shared library libstdc++.so.6: No such file or directory (needed by /app/erts-12.2.1/bin/beam.smp)
Error loading shared library libgcc_s.so.1: No such file or directory (needed by /app/erts-12.2.1/bin/beam.smmp)

Even though I do have all dependencies installed AFAIK:

    apt install -y \
      openssl \
      libncursesw6 \
      libstdc++6 \
      libgcc-s1 \
      zlib1g \
      wget \
      musl-dev && \

For musl, I had to create a link as well:

ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1

The same procedure for the other libraries like this:

ln -s /lib/x86_64-linux-gnu/libncursesw.so.6 /lib/libncursesw.so.6

did not succeed.

Does anyone know where erlang/elixir looks for shared libraries? And, if I can add options to include the Debian library path /lib/x86_64-linux-gnu/?

You’re doing something wrong and the problem is probably not a library resolution path, but the issue seems to be that the release is compiled on some other system than you run it on.

Do you have a 2-stage Dockerfile that builds the release and then runs it in a different image? i.e. one maybe is Alpine and the other is Debian?

Or are you building the release locally on a different system and then copying it to the Docker image?

Or maybe you are copying the _build directory from the parent system to the Docker image?

Somehow you end up with Erlang being compiled for a different system that it runs on.

1 Like

I was assuming the same thing, as I moved from alpine to Debian.

To make sure, this is not the case, I tested it with the build image itself. The same error appears here when copying it to the target (same) container.

I build the image in an Debian container with elixir/erlang installed and copy everything to the runtime container (Debian slim without elixir/erlang):

FROM debian:bullseye-slim AS app

RUN \
    apt update && \
    apt install -y \
      openssl \
      libncursesw6 \
      libstdc++6 \
      libgcc-s1 \
      zlib1g \
      wget \
      bash \
      musl-dev && \
    ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1 

WORKDIR /app

RUN chown nobody:nogroup /app

USER nobody:nogroup
COPY --chown=nobody:nogroup _build/prod/rel/my_app ./

ENV HOME=/app
CMD ["bin/my_app", "start"]

Hi @christo-ph

It depends on the base image that you are using. Check out the following links as a good starting point for your elixir based docker file:

https://hexdocs.pm/phoenix/releases.html#containers

HTH

1 Like

I am using now the official elixir (slim) images, instead of compiling erlang/elixir directly. This works for the moment.

Still have to find the reason why my own pipeline fails here.

Thank you @hubertlepicki and @DonHubi

1 Like