feat(docker): migrate to golden elixir-builder + elixir-runtime

Replace hexpm/elixir builder with substrate/elixir-builder:1.17.3
(pre-installed hex, rebar3, build-essential). Replace debian:bookworm-slim
runtime with substrate/elixir-runtime:latest (Wolfi base, ncurses,
libstdc++, openssl, UID 1000). Removes ~30 lines of apt-get and
user-creation boilerplate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Tyler J King <tking@guildhouse.dev>
This commit is contained in:
Tyler J King 2026-05-16 09:05:30 -04:00
parent f8788dfba9
commit 524c2f53b8

View file

@ -1,5 +1,3 @@
# syntax=docker/dockerfile:1.7
#
# Guildhall production image — Elixir/Phoenix umbrella release. # Guildhall production image — Elixir/Phoenix umbrella release.
# Multi-stage: builder produces a mix release; runtime is a slim debian # Multi-stage: builder produces a mix release; runtime is a slim debian
# carrying only the OTP release + runtime libs. # carrying only the OTP release + runtime libs.
@ -8,27 +6,14 @@
# Target registry: git.guildhouse.dev/tking/guildhall:<tag> # Target registry: git.guildhouse.dev/tking/guildhall:<tag>
# ---------- Stage 1: builder --------------------------------------------- # ---------- Stage 1: builder ---------------------------------------------
FROM hexpm/elixir:1.17.3-erlang-27.1.2-debian-bookworm-20241202-slim AS builder FROM git.guildhouse.dev/guildhouse/substrate/elixir-builder:1.17.3 AS builder
ENV MIX_ENV=prod \ ENV MIX_ENV=prod \
LANG=C.UTF-8 \ LANG=C.UTF-8 \
LC_ALL=C.UTF-8 LC_ALL=C.UTF-8
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
build-essential \
git \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*
RUN mix local.hex --force && \
mix local.rebar --force
WORKDIR /app WORKDIR /app
# Dep resolution needs every apps/*/mix.exs in an umbrella. Copy them
# before any source so dep-layer cache survives source-only edits.
COPY mix.exs mix.lock ./ COPY mix.exs mix.lock ./
COPY config/config.exs config/prod.exs config/runtime.exs config/ COPY config/config.exs config/prod.exs config/runtime.exs config/
COPY apps/guildhall_chronicle/mix.exs apps/guildhall_chronicle/ COPY apps/guildhall_chronicle/mix.exs apps/guildhall_chronicle/
@ -40,62 +25,24 @@ COPY apps/guildhall_web/mix.exs apps/guildhall_web/
RUN mix deps.get --only prod && \ RUN mix deps.get --only prod && \
mix deps.compile mix deps.compile
# Source — copied after dep layers so app-source changes don't bust
# the dep cache.
COPY apps/ apps/ COPY apps/ apps/
# Asset pipeline for guildhall_web — tailwind + esbuild + phx.digest.
# The aliases in apps/guildhall_web/mix.exs define `assets.deploy` as
# `tailwind guildhall_web --minify` + `esbuild guildhall_web --minify`
# + `phx.digest`. `tailwind.install` and `esbuild.install` pull the
# binaries on first use.
COPY apps/guildhall_web/assets apps/guildhall_web/assets COPY apps/guildhall_web/assets apps/guildhall_web/assets
RUN cd apps/guildhall_web && \ RUN cd apps/guildhall_web && \
mix assets.setup && \ mix assets.setup && \
mix assets.deploy mix assets.deploy
# Compile the full umbrella + cut the release. Release name `guildhall`
# is derived from the umbrella mix.exs (no explicit releases: block, so
# it defaults to the project's apps_path-rooted umbrella name).
RUN mix compile --warnings-as-errors && \ RUN mix compile --warnings-as-errors && \
mix release --overwrite mix release --overwrite
# ---------- Stage 2: runtime -------------------------------------------- # ---------- Stage 2: runtime (Wolfi — golden elixir-runtime) -------------
FROM debian:bookworm-slim AS runtime FROM git.guildhouse.dev/guildhouse/substrate/elixir-runtime:latest AS runtime
ENV LANG=en_US.UTF-8 \
LC_ALL=en_US.UTF-8 \
LANGUAGE=en_US:en
# Runtime deps the compiled release needs. locales for the en_US.UTF-8
# generation; libstdc++6 for the erlang ports; libncurses6 for the
# beam; openssl for tls; libsystemd0 for the logger integration some
# releases use; tini as a minimal pid-1 for reapability.
RUN apt-get update -qq && \
apt-get install -y --no-install-recommends \
openssl \
libncurses6 \
libstdc++6 \
libsystemd0 \
locales \
ca-certificates \
curl \
tini \
&& sed -i '/^# en_US.UTF-8 UTF-8/s/^# //' /etc/locale.gen \
&& locale-gen en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/*
# Non-root user. uid 1000 matches the rest of the cluster's convention.
RUN groupadd --system --gid 1000 guildhall && \
useradd --system --uid 1000 --gid guildhall --shell /usr/sbin/nologin \
--home /app --create-home guildhall
WORKDIR /app WORKDIR /app
# Release name `guildhall` produces the release at this path. COPY --from=builder --chown=substrate:substrate /app/_build/prod/rel/guildhall /app
COPY --from=builder --chown=guildhall:guildhall /app/_build/prod/rel/guildhall /app
USER guildhall USER 1000
ENV HOME=/app \ ENV HOME=/app \
PHX_SERVER=true \ PHX_SERVER=true \
@ -106,5 +53,5 @@ EXPOSE 4000
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD curl -fsS http://localhost:4000/health || exit 1 CMD curl -fsS http://localhost:4000/health || exit 1
ENTRYPOINT ["/usr/bin/tini", "--"] ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/app/bin/guildhall", "start"] CMD ["/app/bin/guildhall", "start"]