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
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.
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