Three-stage build. A python:3.12-slim-bookworm stage installs Flask and
stages the interpreter's link libraries; the runtime is
gcr.io/distroless/cc-debian12 with /usr/local copied over, so we ship a
current Python without the shell, apt, perl and tar that make up most of a
slim image's post-exploitation toolkit.
Bookworm on the build side so glibc matches the debian12 runtime. We
deliberately do not use gcr.io/distroless/python3-debian12 — its pinned
interpreter carries a larger CVE count than the slim image it would replace.
The container now runs as nonroot (65532), so /data is created and chowned
in the build stage: registry.db, databases/, uploads/ and inbox/ are written
there at startup and there is no shell left to fix ownership at runtime.
CMD becomes an exec-form ENTRYPOINT for the same reason.
Note for deploys: docker-compose.yml bind-mounts ./data:/data, and a
host-owned directory will need to be writable by uid 65532.