# syntax=docker/dockerfile:1 # --- build stage: compile a static, CGO-free binary --- FROM golang:1.26-alpine AS build ARG COVER_DIR=/covers WORKDIR /src # Dependencies first for layer caching (changes rarely). COPY go.mod go.sum ./ RUN go mod download # Then source (changes often). internal/web carries the go:embed'd # templates/static assets — missing them turns the embed directive into a # build error, so the whole tree must land before `go build`. COPY *.go ./ COPY internal/ ./internal/ # Static binary: the Postgres driver (jackc/pgx) is pure Go, so CGO_ENABLED=0 # leaves no libc dependency. # -trimpath + -ldflags strip paths and debug info for a smaller image. RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/server . # Create the source directory; runtime COPY sets ownership for the named volume. RUN mkdir -p "$COVER_DIR" # --- runtime stage: distroless static, non-root --- FROM gcr.io/distroless/static:nonroot ARG COVER_DIR=/covers WORKDIR / COPY --from=build --chown=65532:65532 ${COVER_DIR} ${COVER_DIR} COPY --from=build /out/server /server EXPOSE 8080 USER nonroot:nonroot ENV PORT=8080 ENTRYPOINT ["/server"]