Download this file
| 1 | # ---- build ---- |
| 2 | # Keep this in step with go.mod's `go` directive when it bumps. |
| 3 | FROM golang:1.25-alpine AS build |
| 4 | WORKDIR /src |
| 5 | COPY go.mod go.sum ./ |
| 6 | RUN go mod download |
| 7 | COPY . . |
| 8 | # Pure-Go SQLite (modernc) means we can build a fully static binary with no cgo. |
| 9 | RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /lchat . |
| 10 | # Staged here so the runtime image (which has no shell to mkdir with) can copy |
| 11 | # in a /data already owned by nonroot — a named volume then inherits writable |
| 12 | # ownership on first use. A bind mount still needs a host-side chown to 65532. |
| 13 | RUN mkdir -p /data |
| 14 | |
| 15 | # ---- run ---- |
| 16 | # distroless/static:nonroot: ~2MB, no shell, runs as uid 65532 — the container |
| 17 | # never needs root. The frontend and SQLite engine are embedded in /lchat. |
| 18 | FROM gcr.io/distroless/static-debian12:nonroot |
| 19 | COPY --from=build --chown=nonroot:nonroot /data /data |
| 20 | COPY --from=build /lchat /lchat |
| 21 | # Runtime config comes from env: LCHAT_DB (point it at /data), ADDR, |
| 22 | # LCHAT_ADMIN_TOKEN. See README.md § Docker. |
| 23 | EXPOSE 1747 |
| 24 | VOLUME /data |
| 25 | ENTRYPOINT ["/lchat"] |
| 26 | |