forked from jappel/leistungsbilanz-ts
Add production compose stack and stop idle load in containers
The development stack was running permanently on a server: polling file watchers, a healthcheck that rendered a full page every five seconds and no memory limit grew next dev to 10 GB and pushed the host into swap. - add compose.prod.yaml running compiled output in separate api/web services - make the Dockerfile multi-stage with dev and prod targets, prune devDependencies and run the runtime image as node instead of root - bake API_INTERNAL_URL at build time; next start ignores it at runtime because rewrite destinations are resolved into routes-manifest.json - drop CHOKIDAR_USEPOLLING and WATCHPACK_POLLING - probe /health instead of /, which redirects to /projects and made every healthcheck render the project list - give every service a memory limit and forbid swap in production - rename the development compose project to leistungsbilanz-dev so its down command cannot target the production stack - bind development ports to localhost - close the http server and the SQLite handle on SIGTERM/SIGINT - match probe user agents in the navigation log filter; Node's fetch sends one, so the previous check never matched - exit docker-start.sh when either supervised process dies - remove drizzle.config.js, a compiled copy drizzle-kit never reads, and the pre-Next index.html/styles.css leftovers Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
a17e2e3f4b
commit
01fa527b9c
14 changed files with 424 additions and 118 deletions
33
AGENTS.md
Normal file → Executable file
33
AGENTS.md
Normal file → Executable file
|
|
@ -531,13 +531,44 @@ Users must be able to override sizing suggestions.
|
|||
- Preserve stable UUIDs and explicit transaction boundaries for a later
|
||||
PostgreSQL adapter.
|
||||
|
||||
## Deployment Rules
|
||||
|
||||
There are two compose files and they must stay separate.
|
||||
|
||||
- `compose.yaml` is development only. Project name `leistungsbilanz-dev`, ports
|
||||
bound to `127.0.0.1`, watch-mode servers, source bind mounts.
|
||||
- `compose.prod.yaml` is the deployment. Project name `leistungsbilanz`, image
|
||||
target `prod`, compiled output, no bind mounts, no file watchers.
|
||||
|
||||
Rules that a running deployment depends on:
|
||||
|
||||
- Never run the development stack permanently. `next dev` and `tsx watch`
|
||||
produce load and grow in memory with no user activity.
|
||||
- Never reintroduce `CHOKIDAR_USEPOLLING` or `WATCHPACK_POLLING`. They make the
|
||||
watcher poll the source tree continuously.
|
||||
- Container healthchecks target `/health` only. `/` is a redirect to
|
||||
`/projects`, and `fetch` follows redirects, so probing `/` renders a full
|
||||
page on every interval.
|
||||
- Every service keeps a `mem_limit`; production services also keep a
|
||||
`memswap_limit` of the same size so a leak kills the container instead of the
|
||||
host.
|
||||
- The production image runs as `node`. Data volumes written by an earlier root
|
||||
container need a one-time `chown` (see `docs/deployment.md`).
|
||||
- The Express API is not published on the host. It has no authentication and is
|
||||
reached through the Next.js rewrite.
|
||||
- Development migrates with `drizzle-kit`; the production image has no
|
||||
devDependencies and migrates with `node scripts/run-migrations.js`.
|
||||
- `SIGTERM`/`SIGINT` must close the HTTP server and the SQLite handle and then
|
||||
exit. Do not reduce these handlers to logging.
|
||||
|
||||
## Current Deferred Work
|
||||
|
||||
- Revit/CSV/IFCGUID round-trip, except when Phase 14 is explicitly requested and
|
||||
`docs/spec/revit-csv-integration-requirements.md` is being followed
|
||||
- full electrical sizing
|
||||
- multi-user/PostgreSQL operation
|
||||
- supported production deployment
|
||||
- authentication, authorization and TLS termination; until they exist the
|
||||
deployment belongs in a trusted network or behind an authenticating proxy
|
||||
|
||||
Do not implement these while working on an unrelated phase.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue