From a615b0aee7c715963981cd60577d012c13ebafe6 Mon Sep 17 00:00:00 2001 From: fabi Date: Sun, 31 May 2026 17:26:58 +0200 Subject: [PATCH] fix(docker): unblock image builds on this host - backend dep-cache stage stubs only main.rs/lib.rs, but Cargo.toml declares a second [[bin]] crawler at src/bin/crawler.rs, so `cargo build --locked` aborts ("can't find bin crawler"). Stub it too. - runtime was debian:bookworm-slim (glibc 2.36) while rust:1-slim now tracks trixie (glibc 2.41) -> "GLIBC_2.39 not found" at boot. Pin the runtime to debian:trixie-slim so it matches the builder's glibc. - frontend healthcheck probed localhost (-> musl picks IPv6 ::1) but the Node server binds IPv4 0.0.0.0 only -> false "unhealthy". Probe 127.0.0.1. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/Dockerfile | 8 ++++++-- frontend/Dockerfile | 10 ++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 964cbb9..fd4f87c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,7 +10,8 @@ RUN apt-get update \ # exact crate versions CI tested. Without Cargo.lock + the flag, cargo # would silently resolve fresh on every image build. COPY Cargo.toml Cargo.lock ./ -RUN mkdir src && echo "fn main() {}" > src/main.rs && echo "" > src/lib.rs \ +RUN mkdir -p src/bin && echo "fn main() {}" > src/main.rs && echo "" > src/lib.rs \ + && echo "fn main() {}" > src/bin/crawler.rs \ && cargo build --locked --release \ && rm -rf src @@ -18,7 +19,10 @@ COPY src ./src COPY migrations ./migrations RUN touch src/main.rs src/lib.rs && cargo build --locked --release -FROM debian:bookworm-slim +FROM debian:trixie-slim +# Runtime base must match the builder's Debian release: `rust:1-slim` tracks +# trixie (glibc 2.41), so a bookworm runtime (glibc 2.36) can't run the +# binary ("GLIBC_2.39 not found"). Keep these two in lockstep on bumps. # `curl` is for the container HEALTHCHECK; `ca-certificates` is for # outbound HTTPS (crawler covers/pages). RUN apt-get update \ diff --git a/frontend/Dockerfile b/frontend/Dockerfile index dcca067..33f3824 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -24,10 +24,12 @@ COPY --from=builder --chown=node:node /app/package.json ./ USER node EXPOSE 3000 -# Alpine's busybox `wget` is the canonical lightweight HTTP probe. -# `--spider` doesn't follow redirects; `node build` serves a 200 on -# `/` for the homepage so this works without a dedicated /health. +# Alpine's busybox `wget` is the canonical lightweight HTTP probe. Probe +# 127.0.0.1, not `localhost`: musl resolves `localhost` to IPv6 ::1 first, +# but the Node server binds IPv4 0.0.0.0 only, so a localhost probe gets +# "connection refused" and the container is wrongly marked unhealthy. Use a +# GET (`-O /dev/null`) since `node build` serves 200 on `/`. HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD wget -q --spider http://localhost:3000/ || exit 1 + CMD wget -q -O /dev/null http://127.0.0.1:3000/ || exit 1 CMD ["node", "build"]