Compare commits

...

1 Commits

Author SHA1 Message Date
mAi
78b37f442d fix(docker): pre-create /app/data 1000:1000 so the binary can mkdir at boot
The first redeploy after slice 2 turned up a latent bug: without a bind
mount at /app/data, the container as UID 1000 can't os.MkdirAll
/app/data because /app (created by WORKDIR) is owned by root with 0755.

mDock works because the bind mount overlays /app/data with the host dir
(owned by m:m), so MkdirAll on the pre-existing dir is a no-op. But any
ephemeral run (smoke tests, CI, anyone running the image without -v)
crashes with 'mkdir /app/data: permission denied'.

Fix: build the empty data dir in the builder stage with `chown -R
1000:1000`, then COPY --from=build --chown=1000:1000 it into the
distroless final image. The bind mount continues to overlay it on
mDock without needing changes.

Verified: docker run -d (no -v) → /api/healthz returns {"status":"ok"}
and the data dir is writable.
2026-05-15 18:27:40 +02:00

View File

@@ -20,17 +20,25 @@ RUN CGO_ENABLED=0 GOOS=linux go build \
-o /out/mcables \
./cmd/mcables
# Pre-create the runtime data dir with the right owner in the builder
# stage, then COPY it into the distroless final image. Distroless has
# no shell + no mkdir, so this is the canonical pattern for "writable
# subdir under a non-root user".
RUN mkdir -p /out/data && chown -R 1000:1000 /out/data
FROM gcr.io/distroless/static-debian12:nonroot
WORKDIR /app
COPY --from=build /out/mcables /app/mcables
COPY --from=build --chown=1000:1000 /out/data /app/data
ENV MCABLES_ADDR=0.0.0.0:7777 \
MCABLES_DB=/app/data/mcables.db
EXPOSE 7777
# Run as UID:GID 1000:1000 to match m on mDock — the bind-mounted
# /home/m/stacks/mcables/data is owned by m:m, so the container can write
# to it without chowning the host dir. distroless/static-debian12 accepts
# arbitrary numeric UIDs; the Go binary doesn't need a /etc/passwd entry.
# /home/m/stacks/mcables/data is owned by m:m, so the container can
# write to it without chowning the host dir. distroless/static-debian12
# accepts arbitrary numeric UIDs; the Go binary doesn't need a
# /etc/passwd entry.
USER 1000:1000
ENTRYPOINT ["/app/mcables"]