generated from bastian/boilerplate
Initial commit
This commit is contained in:
139
docs/deployment.md
Normal file
139
docs/deployment.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user