ARG ELIXIR_VERSION=1.18.4 ARG OTP_VERSION=27.2.4 ARG DEBIAN_VERSION=bullseye-20250520-slim ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}" # Use distroless base image - this includes glibc and essential libraries ARG RUNNER_IMAGE="gcr.io/distroless/cc-debian11:nonroot" FROM ${BUILDER_IMAGE} AS builder # install build dependencies RUN apt-get update -y && \ apt-get upgrade -y && \ apt-get install -y build-essential git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # prepare build dir WORKDIR /app # 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 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 # Final distroless stage FROM ${RUNNER_IMAGE} # Set environment variables for production ENV MIX_ENV="prod" \ LANG=C.UTF-8 \ # Disable history files for security HISTFILE=/dev/null \ # Set HOME to /tmp (writable in distroless) HOME=/tmp \ # Configure Erlang VM ERL_AFLAGS="+S 1:1 +A 1 +K true" \ PHX_SERVER=true WORKDIR /app # Copy the Elixir release from builder stage # nonroot user in distroless has UID 65532 COPY --from=builder --chown=65532:65532 /app/_build/prod/rel/aprs ./ # Add security metadata LABEL org.opencontainers.image.vendor="APRS.me" \ org.opencontainers.image.title="APRS.me Server (Distroless)" \ org.opencontainers.image.description="APRS.me server with distroless base" \ security.distroless="true" \ security.nonroot="true" # Run the server ENTRYPOINT ["/app/bin/server"] EXPOSE $PORT