# syntax=docker/dockerfile:1 # --- build stage: compile a static, CGO-free binary --- FROM golang:1.24-alpine AS build WORKDIR /src # Dependencies first for layer caching (changes rarely). COPY go.mod go.sum ./ RUN go mod download # Then source (changes often). # Source plus the go:embed'd assets. Missing either directory turns the embed # directive into a build error, so both must be copied before `go build`. COPY *.go ./ COPY templates/ ./templates/ COPY static/ ./static/ # Static binary: pure-Go sqlite means CGO_ENABLED=0 -> 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 . # Data dir with the runtime user's ownership so the mounted volume inherits it. RUN mkdir -p /out/data # --- runtime stage: distroless static, non-root --- FROM gcr.io/distroless/static:nonroot WORKDIR / COPY --from=build /out/server /server COPY --from=build --chown=65532:65532 /out/data /data VOLUME ["/data"] EXPOSE 8080 USER nonroot:nonroot ENV DB_PATH=/data/bookmarks.db PORT=8080 ENTRYPOINT ["/server"]