Files
flat-pilot/docs/deployment.md
2026-07-19 13:09:04 +02:00

140 lines
4.0 KiB
Markdown

# Deployment und Betrieb
Die Anwendung wird als ein Docker-Image ausgeliefert. Das Image enthaelt das
gebaute NestJS-Backend und das gebaute Angular-Frontend.
## Release-Build
Vor jedem Release:
```bash
npm ci
npm run lint
npm run format:check
npm run typecheck
npm test
npm run build
docker build -t registry.example.com/business-app:<tag> .
```
`npm run build` fuehrt aus:
1. API-Client generieren
2. API-Client bauen
3. Backend bauen
4. Frontend bauen
5. Frontend nach `apps/backend/dist/public` kopieren
Das Dockerfile baut erneut im Container und erzeugt anschliessend ein schlankes
Runtime-Image mit Non-Root-User.
## Runtime-Konfiguration
Konfiguration erfolgt ueber Umgebungsvariablen. Nutze `.env.example` nur als
Vorlage. Production-Secrets gehoeren in Secret Management, CI/CD Variables oder
eine geschuetzte Server-Konfiguration.
Wichtige Produktionswerte:
- `NODE_ENV=production`
- `APP_BASE_URL=https://app.example.com`
- `FRONTEND_BASE_URL=https://app.example.com`
- `TRUST_PROXY=true`, wenn hinter Reverse Proxy
- `DATABASE_SSL=true`, wenn die Datenbank TLS erzwingt
- `SWAGGER_ENABLED=false`, ausser bewusst anders entschieden
- starke Werte fuer `SESSION_SECRET`, `SESSION_ENCRYPTION_KEY`, `OIDC_CLIENT_SECRET`
## Migrationen
Migrationen werden nicht beim App-Start ausgefuehrt. Fuehre sie vor dem neuen
App-Container aus, mit demselben Image und derselben Konfiguration:
```bash
docker run --rm --env-file .env registry.example.com/business-app:<tag> node apps/backend/dist/database/run-migrations.js
```
Danach den App-Container starten oder aktualisieren. Wenn Migrationen fehlen,
schlaegt der App-Start fehl beziehungsweise `/health/ready` bleibt nicht bereit.
## Container starten
Ein einfaches Compose-Beispiel liegt in `compose.yml`:
```bash
docker compose up -d
```
Der Container:
- laeuft als Non-Root-User
- verwendet ein read-only Root Filesystem
- nutzt `/tmp` als tmpfs
- dropt Linux Capabilities
- prueft `/health/ready` als Healthcheck
Compose baut oder nutzt das Image `internal-business-app:latest`. Fuer echte
Deployments sollte ein versioniertes Registry-Image verwendet werden.
## Reverse Proxy
Nginx oder ein Load Balancer sollte TLS terminieren und alle Routen an den
App-Container weiterleiten. Die Angular-Dateien werden nicht separat durch Nginx
ausgeliefert. Ein Beispiel liegt in `docs/nginx-example.conf`.
Wichtig:
- WebSocket-Konfiguration ist fuer dieses Boilerplate nicht erforderlich.
- `X-Forwarded-Proto` und `X-Forwarded-For` sollten gesetzt werden.
- `APP_BASE_URL` muss zur externen HTTPS-URL passen.
- Wenn `TRUST_PROXY=true` gesetzt ist, muss der Proxy vertrauenswuerdig sein.
## Healthchecks
- `/health/live`: Prozess lebt.
- `/health/ready`: Datenbank erreichbar, Migration-Check initialisiert und keine
offenen Migrationen.
Readiness ist der richtige Check fuer Rolling Deployments und Container
Orchestrierung.
## TeamCity-Beispiel
1. Checkout
2. `npm ci`
3. `npm run lint`
4. `npm run format:check`
5. `npm run typecheck`
6. `npm test`
7. `npm run build`
8. `docker build -t <registry>/<image>:<build-number> .`
9. `docker push <registry>/<image>:<build-number>`
10. Migration-Job mit neuem Image ausfuehren
11. App-Service auf neues Image aktualisieren
12. `/health/ready` pruefen
## Rollback
Ein Rollback ist nur dann einfach, wenn die Datenbankmigrationen rueckwaerts
kompatibel geplant wurden. Fuer riskante Schema-Aenderungen sollte das Expand-
Contract-Muster verwendet werden:
1. Neue Spalten oder Tabellen hinzufuegen, alte weiter bedienen.
2. Anwendung umstellen.
3. Daten migrieren.
4. Alte Spalten oder Pfade in einem spaeteren Release entfernen.
## Betrieb
Beobachte mindestens:
- HTTP-Fehlerraten und Latenzen
- Healthcheck-Status
- Datenbankverbindungen
- Login-Fehler vom OIDC Provider
- `MIGRATION_MISSING`
- Rate-Limit-Treffer, insbesondere `RATE_LIMIT_EXCEEDED` auf Login- und Admin-Endpunkten
- Audit-Log fuer administrative Aktionen
Logs sollten zentral gesammelt werden. Request IDs helfen dabei, Frontend-Fehler,
Backend-Logs und Audit-Eintraege zusammenzufuehren.