Files
librenotes/Dockerfile
Michael Czechowski 635a03098b Add Dockerfile, Compose stacks, and /healthz endpoint
Dockerfile is multi-stage:
- build: golang:1.25-bookworm, CGO_ENABLED=0 (modernc.org/sqlite
  is pure-Go) + -trimpath + -ldflags "-s -w" so the resulting
  binary is small and reproducible-ish.
- runtime: gcr.io/distroless/static:nonroot, ~2 MB. Runs as uid
  65532. /data and /var/lib/librenotes are declared volumes so
  per-tenant notes and the SQLite database survive container
  restarts.

healthcheck subcommand: distroless static has no shell or
wget/curl, so /healthz is reachable but no client to call it. A
new "librenotes healthcheck" subcommand uses net/http to GET
$LIBRENOTES_HEALTHCHECK_URL (default 127.0.0.1:8080/healthz) and
exits non-zero on failure. Both compose files invoke it from the
HEALTHCHECK directive.

httpapi adds a tiny GET /healthz that returns {"status":"ok"}
(no DB ping yet — added when readiness probes need it).

docker-compose.yml: dev stack on :8080 with named volumes and a
LogMailer; everything via env vars, JWT secret defaulted to a
dev value.
docker-compose.prod.yml: layered overrides — pulls a registry
image, expects LIBRENOTES_* env, sets memory limits and JSON-
file log rotation.

Closes #25.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 22:47:42 +02:00

43 lines
1.3 KiB
Docker

# Multi-stage Dockerfile for librenotes.
#
# Stage 1: build the static, CGO-free binary. modernc.org/sqlite
# is pure-Go so we don't need libc; this lets us drop the runtime
# image to gcr.io/distroless/static, which is ~2 MB.
#
# Stage 2: run as non-root (distroless static's "nonroot" user,
# uid 65532) with /data and /var/lib/librenotes mounted from
# named volumes so the database and per-tenant note files survive
# container restarts.
# ---- build ----
FROM golang:1.25-bookworm AS build
WORKDIR /src
# Cache module downloads on a separate layer.
COPY go.mod go.sum ./
RUN go mod download
COPY . .
ARG VERSION=dev
ARG BUILDTIME
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go build \
-trimpath \
-ldflags "-s -w \
-X git.librete.ch/public/librenotes/internal/notesium.gitversion=${VERSION} \
-X git.librete.ch/public/librenotes/internal/notesium.buildtime=${BUILDTIME}" \
-o /out/librenotes \
./cmd/librenotes
# ---- runtime ----
FROM gcr.io/distroless/static:nonroot AS runtime
COPY --from=build /out/librenotes /librenotes
USER nonroot:nonroot
EXPOSE 8080
VOLUME ["/data", "/var/lib/librenotes"]
ENV LIBRENOTES_ADDR=":8080" \
LIBRENOTES_DATA_DIR="/data" \
LIBRENOTES_DB="/var/lib/librenotes/librenotes.db"
ENTRYPOINT ["/librenotes", "serve"]