# syntax=docker/dockerfile:1.7 # # Guildhall production image — Elixir/Phoenix umbrella release. # Multi-stage: builder produces a mix release; runtime is a slim debian # carrying only the OTP release + runtime libs. # # Build context: the guildhall umbrella root. # Target registry: git.guildhouse.dev/tking/guildhall: # ---------- Stage 1: builder --------------------------------------------- FROM hexpm/elixir:1.17.3-erlang-27.1.2-debian-bookworm-20241202-slim AS builder ENV MIX_ENV=prod \ LANG=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 # 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 config/config.exs config/prod.exs config/runtime.exs config/ COPY apps/guildhall_chronicle/mix.exs apps/guildhall_chronicle/ COPY apps/guildhall_graph_bridge/mix.exs apps/guildhall_graph_bridge/ COPY apps/guildhall_ops_db/mix.exs apps/guildhall_ops_db/ COPY apps/guildhall_orchestrator/mix.exs apps/guildhall_orchestrator/ COPY apps/guildhall_web/mix.exs apps/guildhall_web/ RUN mix deps.get --only prod && \ mix deps.compile # Source — copied after dep layers so app-source changes don't bust # the dep cache. 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 RUN cd apps/guildhall_web && \ mix assets.setup && \ 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 && \ mix release --overwrite # ---------- Stage 2: runtime -------------------------------------------- FROM debian:bookworm-slim 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 # Release name `guildhall` produces the release at this path. COPY --from=builder --chown=guildhall:guildhall /app/_build/prod/rel/guildhall /app USER guildhall ENV HOME=/app \ PHX_SERVER=true \ PORT=4000 EXPOSE 4000 HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ CMD curl -fsS http://localhost:4000/health || exit 1 ENTRYPOINT ["/usr/bin/tini", "--"] CMD ["/app/bin/guildhall", "start"]