diff --git a/Dockerfile b/Dockerfile index aaac065..8c44e88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,36 @@ +# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian +# instead of Alpine to avoid DNS resolution issues in production. +# +# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu +# https://hub.docker.com/_/ubuntu?tab=tags +# +# This file is based on these images: +# +# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image +# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20240904-slim - for the release image +# - https://pkgs.org/ - resource for finding needed packages +# - Ex: hexpm/elixir:1.17.2-erlang-27.0.1-debian-bullseye-20240904-slim +# ARG ELIXIR_VERSION=1.17.2 -FROM elixir:$ELIXIR_VERSION as base -############################################################################## -FROM base as build +ARG OTP_VERSION=27.0.1 +ARG DEBIAN_VERSION=bullseye-20240904-slim -RUN apt-get update -qq && \ - DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \ - build-essential \ +ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}" +ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}" +#################################################################################################### +FROM ${BUILDER_IMAGE} as package_installer + +# install build dependencies +RUN apt-get update -y && apt-get install -y build-essential \ + git \ locales \ - inotify-tools && \ - apt-get clean && \ - update-locale LANG=C.UTF-8 LC_ALL=C.UTF-8 -############################################################################## -FROM build as final + inotify-tools \ + && apt-get clean && rm -f /var/lib/apt/lists/*_* +# prepare build dir WORKDIR /app - +#################################################################################################### +FROM package_installer as development RUN mix local.hex --force && \ mix archive.install hex phx_new --force && \ mix local.rebar --force @@ -22,3 +38,75 @@ RUN mix local.hex --force && \ COPY . . CMD [ "bash" ] +#################################################################################################### +FROM package_installer as builder + +# install hex + rebar +RUN mix local.hex --force && \ + mix local.rebar --force + +# set build ENV +ENV MIX_ENV="prod" + +# install mix dependencies +COPY mix.exs mix.lock ./ +RUN mix deps.get --only $MIX_ENV +RUN mkdir config + +# copy compile-time config files before we compile dependencies +# to ensure any relevant config change will trigger the dependencies +# to be re-compiled. +COPY config/config.exs config/${MIX_ENV}.exs config/ +RUN mix deps.compile + +COPY priv priv + +COPY lib lib + +COPY assets assets + +# compile assets +RUN mix assets.deploy + +# Compile the release +RUN mix compile + +# Changes to config/runtime.exs don't require recompiling the code +COPY config/runtime.exs config/ + +COPY rel rel +RUN mix release +#################################################################################################### + +# start a new build stage so that the final image will only contain +# the compiled release and other runtime necessities +FROM ${RUNNER_IMAGE} + +RUN apt-get update -y && \ + apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates \ + && apt-get clean && rm -f /var/lib/apt/lists/*_* + +# Set the locale +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen + +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +WORKDIR "/app" +RUN chown nobody /app + +# set runner ENV +ENV MIX_ENV="prod" + +# Only copy the final release from the build stage +COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/phoenix_deploy_test ./ + +USER nobody + +# If using an environment that doesn't automatically reap zombie processes, it is +# advised to add an init process such as tini via `apt-get install` +# above and adding an entrypoint. See https://github.com/krallin/tini for details +# ENTRYPOINT ["/tini", "--"] + +CMD ["/app/bin/server"]