Finally took the jump to docker deployments. Here is the Dockerfile I ended up with

Daemon mode doesn’t work inside a Docker container, it has to run the foreground for Docker to know that it’s running, and daemon mode runs the process in the background, so Docker thinks it’s done, and exits. You’ll want to continue to use start and set restart: always in your docker-compose file, https://docs.docker.com/compose/compose-file/#restart

1 Like

Thank you, it’s almost working : )

Just one thought on the shell scripting: the

cat mix.exs | grep app: | sed -e 's/ app: ://' | tr ',' ' ' | sed 's/ //g' > app_name.txt

line can be written as

grep "app:" mix.exs | sed 's/^.*app:.*:\([^,]*\),/\1/' > app_name.txt

Start only two external commands instead of five. If looks to be too complicated, at least remove the cat in from of the grep, grep can read files.

I’ve created a dockerfile that runs in OpenShift/Kubernetes, and I am working to finish it, based on the one from documentation but with a few tweaks for the security model in OpenShift and using Fedora as the base image:

It uses Fedora as the basis:

  • Gets the source code and generates a release
  • Creates another container that uses the release

You need to set up SECRET_KEY_BASE in the environment as it will use it when running.
The example repo does not have a database, to make it easier to use.

I will be updating it until it works flawlessly.

1 Like

I’ve updated the Dockerfile (to the latest version) and the example Phoenix app (that is getting old and will be updated when the new release is out).

Highlights:

  • The dockerfile creates a release and uses that for actually running the app.
  • Your code needs to be set up in a environment variable (SRC_CODE) or it will use the default.
  • Based on Fedora 34
  • Allows you to define the environment (MIX_ENV) when building, with a default of production.

The example phoenix app:

  • It has two pages: you can go from one to the other. It helps to test that services are properly configured in production. Not too complex.
  • You need to setup SECRET_KEY_BASE in your deployment or it won’t work.
  • There is no database (no ecto), so you don’t struggle to configure it.
  • The second page will show the content of a variable called MY_STRING in your deployment, so you are sure that it works as a 12 factor app. You can extend that config (in releases) to whatever your application needs (i.e. database config when you are actually using a database in your deployment.

Here is my version using ubuntu 20.04 as a base image so it matches what is in my production server

FROM ubuntu:20.04 AS build

ARG USER=builder
ARG UID=1000
ARG GID=1000
ARG PWD=builder

RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y apt-transport-https ca-certificates gnupg software-properties-common wget

RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2> /dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg > /dev/null

RUN apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main'

RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -

RUN apt-add-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main'

RUN apt-get update

RUN DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y apt-utils

RUN apt-get update

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y clang-12 capnproto

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y git

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y cmake

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y curl

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libssl-dev automake autoconf libncurses5-dev

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y xsltproc fop libxml2-utils

RUN update-alternatives --install /usr/bin/cc cc /usr/bin/clang-12 10
RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-12 10

RUN useradd -m $USER --uid $UID
RUN echo "${USER}:${PWD}" | chpasswd

USER ${UID}:${GID}

ENV LANG=C.UTF-8

ENV TERM=xterm-256color

RUN curl https://sh.rustup.rs -sSf | bash -s -- -y

RUN echo 'source $HOME/.cargo/env' >> ~/.bashrc

RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.8.1

RUN echo 'source $HOME/.asdf/asdf.sh' >> ~/.bashrc

ENV PATH="/home/${USER}/.asdf/bin:${PATH}"
ENV PATH="/home/${USER}/.asdf/shims:${PATH}"

RUN /bin/bash -c "asdf plugin add erlang"

RUN /bin/bash -c "asdf plugin add elixir"

RUN /bin/bash -c "asdf install erlang 24.0.2"

RUN /bin/bash -c "asdf global erlang 24.0.2"

RUN /bin/bash -c "asdf install elixir 1.12.1-otp-24"

RUN /bin/bash -c "asdf global elixir 1.12.1-otp-24"

RUN echo 'PS1="(builder) $PS1"' >> ~/.bashrc

RUN /bin/bash -c "HEX_MIRROR=https://cdn.jsdelivr.net/hex mix local.hex --force"
RUN /bin/bash -c "HEX_MIRROR=https://cdn.jsdelivr.net/hex mix local.rebar --force"

WORKDIR /home/${USER}/project

CMD ["/bin/bash"]

Note that this image install some dependencies that my backend needs like rust for example too.

I build it using

docker build --build-arg USER=$USER   \
             --build-arg UID=$(id -u) \
             --build-arg GID=$(id -g) \
             --no-cache               \
             -t tip-off/builder:v1 . 

and then run it using inside the project directory:

docker run --detach-keys='ctrl-e,e' -it -v$(pwd):/home/$USER/project --rm tip-off/builder:v1
1 Like