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

4.0 KiB

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:

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:

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:

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.