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…
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
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
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:
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):
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.
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.
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