- Dockerfile: node:24-alpine, production deps only, runs as the node
user, healthcheck on /healthz. No volume, because the server keeps
no state.
- docker-compose.yml: example for the VPS. It publishes no ports,
since Docker's port publishing bypasses ufw and would skip NPM's IP
access list. It joins NPM's network instead.
- .gitea/workflows/docker.yml: on v*-prod* tags, builds on the
self-hosted runner and pushes v0idf1sh/sdp-dashboard:<tag> and
:latest using the DHUB_UNAME and DHUB_PASS secrets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>