Skip to content

Commit f68ab0f

Browse files
hyperpolymathclaude
andcommitted
fix(container): repair Containerfile build rot + add runtime.exs for env config
The container/Containerfile build was broken end-to-end; six fixes make `podman build -f container/Containerfile` succeed and produce a runnable REST image: 1. .dockerignore excluded scripts/fetch-cartridges.sh (needed by COPY) and schemas/cartridge-v1.json (Catalog schema mirror) — un-ignored both. 2. Pin Zig to 0.15.1 (.tool-versions) instead of unpinned `apk add zig`, which pulled a newer Zig that removed std.heap.GeneralPurposeAllocator. 3. Elixir builder cgr.dev/chainguard/elixir:latest is now 403/auth-gated → public docker.io/elixir:1.18.4-otp-25. 4. Runtime base cgr.dev/chainguard/wolfi-base lost gcompat/ncurses-libs and its OpenSSL 3 breaks the OTP-25 crypto NIF (needs libcrypto.so.1.1) → debian:bullseye-slim (matches builder ABI). 5. COPY schemas/cartridge-v1.json into /schemas (Catalog requires it at boot). 6. Strip multi-GB .zig-cache from the cartridge tree before the runtime COPY (was exhausting build disk). Plus config/runtime.exs so BOJ_PORT / BOJ_BIND_IP / BOJ_CARTRIDGES_ROOT are read at release boot, not baked at compile time — fixes the listener binding to 127.0.0.1 (unreachable via port-map) and cartridges_loaded:0 (baked build-path). Deployed and verified live on Hetzner: /health returns 200. Refs #271, #272. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ed5c741 commit f68ab0f

3 files changed

Lines changed: 34 additions & 5 deletions

File tree

.dockerignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,5 @@ data/
8383
configs/
8484
k8s/
8585
setup.sh
86+
!scripts/fetch-cartridges.sh
87+
!schemas/cartridge-v1.json

container/Containerfile

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ ARG BOJ_CARTRIDGES_REPO=https://github.com/hyperpolymath/boj-server-cartridges.g
2424

2525
FROM cgr.dev/chainguard/wolfi-base:latest AS zig-builder
2626

27-
RUN apk add --no-cache zig build-base git bash
27+
RUN apk add --no-cache build-base git bash curl xz
28+
# Pin Zig to the repo-declared version (.tool-versions: 0.15.1); wolfi apk zig rolls forward and breaks the build
29+
RUN curl -fsSL https://ziglang.org/download/0.15.1/zig-x86_64-linux-0.15.1.tar.xz -o /tmp/zig.tar.xz \
30+
&& mkdir -p /opt/zig && tar -xJf /tmp/zig.tar.xz -C /opt/zig --strip-components=1
31+
ENV PATH=/opt/zig:${PATH}
2832

2933
WORKDIR /build
3034

@@ -59,7 +63,10 @@ RUN for ffi_dir in /build/cartridges/*/ffi; do \
5963
# Stage 2: Elixir Release Builder
6064
# ============================================================================
6165

62-
FROM cgr.dev/chainguard/elixir:latest AS mix-builder
66+
# Strip Zig build caches (multi-GB, runtime-irrelevant) so the cartridge COPY into the runtime stage stays small
67+
RUN find /build/cartridges -type d -name .zig-cache -prune -exec rm -rf {} + 2>/dev/null || true
68+
69+
FROM docker.io/elixir:1.18.4-otp-25 AS mix-builder
6370

6471
WORKDIR /build
6572

@@ -77,7 +84,7 @@ RUN mix release boj_rest
7784
# Stage 3: Runtime Image
7885
# ============================================================================
7986

80-
FROM cgr.dev/chainguard/wolfi-base:latest
87+
FROM docker.io/debian:bullseye-slim
8188

8289
# OCI labels
8390
LABEL org.opencontainers.image.title="Bundle of Joy Server" \
@@ -90,10 +97,10 @@ LABEL org.opencontainers.image.title="Bundle of Joy Server" \
9097
dev.stapeln.compose="container/compose.toml"
9198

9299
# Minimal runtime deps: OpenSSL (Elixir TLS), ncurses (Erlang), glibc (boj-invoke + .so)
93-
RUN apk add --no-cache ca-certificates openssl ncurses-libs libstdc++ gcompat
100+
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates openssl libncurses6 libstdc++6 && rm -rf /var/lib/apt/lists/*
94101

95102
# Non-root user
96-
RUN addgroup -S appuser && adduser -S appuser -G appuser
103+
RUN groupadd -r appuser && useradd -r -g appuser -d /app appuser
97104

98105
WORKDIR /app
99106

@@ -144,6 +151,9 @@ ENV PORT=7700
144151
ENV MIX_ENV=prod
145152

146153
VOLUME ["/data"]
154+
# Cartridge schema mirror (Catalog validates cartridges against /schemas/cartridge-v1.json)
155+
COPY schemas/cartridge-v1.json /schemas/cartridge-v1.json
156+
147157
USER appuser
148158

149159
EXPOSE 7700

elixir/config/runtime.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
import Config
4+
5+
# Runtime configuration — evaluated at release BOOT, not compile time. Without this,
6+
# a `mix release` bakes config.exs's env lookups at build time, so BOJ_BIND_IP /
7+
# BOJ_PORT / BOJ_CARTRIDGES_ROOT set at `podman run` are ignored (the release keeps
8+
# the build-time values: bind 127.0.0.1 unreachable via port-map, and a build-path
9+
# cartridges_root that yields cartridges_loaded:0). Re-reading them here fixes both.
10+
config :boj_rest,
11+
port: String.to_integer(System.get_env("BOJ_PORT") || "7700"),
12+
bind_ip: System.get_env("BOJ_BIND_IP") || "127.0.0.1",
13+
cartridges_root:
14+
System.get_env("BOJ_CARTRIDGES_ROOT") ||
15+
System.get_env("BOJ_CARTRIDGES_PATH") ||
16+
Path.expand("../../cartridges", __DIR__),
17+
data_dir: System.get_env("BOJ_DATA_DIR") || "/data"

0 commit comments

Comments
 (0)