Elixir Docker Image libncurses

Hello Elixir community,

I’m struggling to get my elixir app running in a docker container, as I keep running into the following error:

/sahnee/erts-10.7.2/bin/beam.smp: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory

From what I understand by doing an evening worth of research, this stems from my docker container lacking the libncurses library which is required by Elixir. What is strange to me is that I am using the official Docker image of Elixir (elixir:1.10), which I assumed contains all libraries, etc required to run Elixir applications?

I intially planned on running the elixir release in a machine without erlang/elixir at all since releases should be self contained (containing erts, etc…), but settled for going the path of least resistance for now.

So my questions are:

  • Is the official Elixir docker repo the recommended way to run elixir applications or do you recommend another one?
  • How would I go about installing every requirement in it?

If relevant, I’ve posted my dockerfile below. As I’m inexperienced with docker I might have made a misake which leads to this error.

Thank you for your time.

Note: My application is not a Phoenix application.

# syntax=docker/dockerfile:1.0.0-experimental

## -------------------------------------------
## NODE
## -------------------------------------------
FROM node:10-alpine as node_build

WORKDIR /sahnee_node
RUN apk add git openssh-client

# Copy the source folder into the Docker image
COPY ./package.json ./package-lock.json ./tsconfig.json ./webpack.config.js /sahnee_node/
COPY ./web /sahnee_node/web

RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan -p 7999 internalgitserver.redacted >> ~/.ssh/known_hosts

RUN --mount=type=ssh,id=sahnee npm ci && \
    NODE_ENV=production npm run build
COPY ./priv/dist /export

## -------------------------------------------
## ELIXIR
## -------------------------------------------
FROM elixir:1.10 as ex_build

WORKDIR /sahnee_elixir
ENV MIX_ENV=prod

# Copy the source folder into the Docker image
COPY ./lib ./priv ./mix.exs ./mix.lock /sahnee_elixir/

# Install dependencies and build Release
RUN mix local.hex --force && \
    mix local.rebar --force && \
    mix deps.get

COPY --from=node_build /export /sahnee_elixir/priv/dist

# Build Release
RUN mix release

# Export data
COPY ./_build/prod/rel/sahnee /export

## -------------------------------------------
## RUN
## -------------------------------------------
FROM elixir:1.10
WORKDIR /sahnee

COPY --from=ex_build /export/ .

EXPOSE 4001

# Set default entrypoint and command
ENTRYPOINT ["/sahnee/bin/sahnee"]
CMD ["start"]

docker -v -> Docker version 19.03.6, build 369ce74a3c

I didn’t know there was an “Official” image? But it sounds like whoever made the image should have an issue opened with them to include that library. It’s basically the terminfo database integration for ncurses, it’s very weird that it’s missing actually…

You should be able to add it in your alpine install by installing the ncurses-libs apk thing if I recall correctly…

Thanks for your reply! :smiley:

I didn’t know there was an “Official” image?

I assumed that the image was the official one since it did not have any prefix and was just called “elixir”. It seems like I was mistaken, thanks for informing me :slight_smile:

But it sounds like whoever made the image should have an issue opened with them to include that library. It’s basically the terminfo database integration for ncurses, it’s very weird that it’s missing actually…

Interestingly, there already is an issue. However, the command posted by the author raises an error.

You should be able to add it in your alpine install by installing the ncurses-libs apk thing if I recall correctly…

I decided against using an alpine image of elixir (even though I typically prefer them) since it did not even finish compiling. The image I am currently using for compiling and running are based on erlang:22 which is based on buster.

When using a buster image to compile my application, but then running it in an alpine container with ncurses-libs this leads to a different error:

/sahnee/releases/0.1.0/../../erts-10.7.2/bin/erl: exec: line 12: /sahnee/erts-10.7.2/bin/erlexec: not found

However, the file /sahnee/erts-10.7.2/bin/erlexec definetly does exist.

Overall it’s a very disheartening situation. I love Elixir and strongly prefer its and Erlangs approach for any system that involves any sort of parallelism. On the other hand I’ve never managed to properly deploy a single Elixir application since I always get stuck along the way :frowning:

On a different note: Would you recommend ditching Docker and going for a bare metal deployment instead? (Well, bare metal in a VM, but you get the idea - no container)

Those “official” images as they are advertised by the docker hub, are just called like this because they were the first or so. They are by no means supported or created by someone from the elixir team.

Even though still not maintained by the core team, though by the hex team, I think the images built by bob can be considered much more official:

2 Likes

On another note: since you’re building a release, there is actually no need to have elixir or erlang installed, the release contains everything necessary.

The only thing you need to make sure is that you run your release in the same OS version as the one you built it in. As such I recommend to use a hex image for building (explicitly defining the OS) and then using this OS as the basis to run your release

You will have to install some missing dependencies for running your release but the resulting image will be a lot smaller this way.


If you decide to use alpine installing the missing dependencies can be done with this command (omit openssl if you don’t need it):

RUN apk add --no-cache bash openssl ncurses-libs
3 Likes

Sorry for the late reply, quite a few things got in the way.

Thanks for your replies, this has helped a lot.
I ended up letting Jenkins use Docker to compile the app, but run it natively afterwards since as you mentioned no longer requires an actual Elixir/Erlang installation once it compiles. Works like a charm so far and saves me from a lot of headaches. :smiley:

2 Likes

hey, how do i know if i need openssl or not? i’m running into some security issues with it.

It’s required for certain parts of OTP, such as crypto, ssh, and ssl. If openssl is missing they won’t be included. Whether or not you need it depends on your application.

https://www.erlang.org/doc/installation_guide/install#optional-utilities

1 Like

If you get compiler errors that reference back to openssl running alpine 3.16 or earlier, you can install openssl1.1-compat. I’m not sure if the exact package name. The EEF Alpine 3.17 image for OTP 25+ I think is going to be compiled with openssl3 I think, so if you’re on OTP25 or up, try it without the compat package first

1 Like