From 17e740a45f753348ac34903dbec9907f6c40411b Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 17 Mar 2026 12:48:13 +0100 Subject: [PATCH] fix: use absolute paths and static linking in Dockerfile (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #48 ## Problem The Docker container failed to start with: ``` exec ./webhooker: no such file or directory ``` Two root causes: 1. **Relative paths**: `COPY` destination and `CMD` used relative paths (`./webhooker`), depending on `WORKDIR` context. 2. **Dynamic linking** (the actual root cause): The binary was built with CGO enabled on Debian (glibc) via `make build`, but deployed to an Alpine runtime (musl). The kernel couldn't find the glibc dynamic linker (`/lib64/ld-linux-x86-64.so.2`), producing the misleading "no such file or directory" error — even though the file existed on disk. ## Fix - **Absolute paths throughout**: `COPY --from=builder /build/bin/webhooker /app/webhooker` and `CMD ["/app/webhooker"]` — no reliance on WORKDIR. - **Static rebuild for Alpine**: Added a `RUN CGO_ENABLED=1 go build -ldflags '-extldflags "-static"' -o bin/webhooker ./cmd/webhooker` step after `make check`. This rebuilds the binary with static linking so it runs on Alpine without glibc. The `make check` step still runs normally (formatting, linting, tests, dynamic build) — the static rebuild is only for the deployment binary. ## Verification - `docker build .` passes (all checks green) - Container starts successfully and initializes the Fx dependency graph - The README already stated "The runtime binary is statically linked and runs on Alpine" — this fix makes that claim actually true. Co-authored-by: clawbot Reviewed-on: https://git.eeqj.de/sneak/webhooker/pulls/49 Co-authored-by: clawbot Co-committed-by: clawbot --- Dockerfile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9759259..f2d1716 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,6 +42,13 @@ COPY . . # Run all checks (fmt-check, lint, test, build) RUN make check +# Rebuild with static linking for Alpine runtime. +# make check already verified formatting, linting, tests, and compilation. +# The CGO binary from `make build` is dynamically linked against glibc, +# which doesn't exist on Alpine (musl). Rebuild with static linking so +# the binary runs on Alpine without glibc. +RUN CGO_ENABLED=1 go build -ldflags '-extldflags "-static"' -o bin/webhooker ./cmd/webhooker + # alpine:3.21 — 2026-03-01 FROM alpine@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709 @@ -54,7 +61,7 @@ RUN addgroup -g 1000 -S webhooker && \ WORKDIR /app # Copy binary from builder -COPY --from=builder /build/bin/webhooker . +COPY --from=builder /build/bin/webhooker /app/webhooker # Create data directory for all SQLite databases (main app DB + # per-webhook event DBs). DATA_DIR defaults to /data in production. @@ -69,4 +76,4 @@ EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:8080/.well-known/healthcheck || exit 1 -CMD ["./webhooker"] +CMD ["/app/webhooker"]