feat: Backend migriert die Datenbank beim Start selbst statt ueber Job
Backend Image / build-and-push (push) Successful in 2m49s
Frontend Image / build-and-push (push) Successful in 2m31s

Kein separater Kubernetes-Job mehr. Dockerfile-CMD fuehrt jetzt
`npm run migrate:deploy` aus, bevor `node dist/main.js` startet -
Tabellen werden beim ersten Verbinden automatisch angelegt. Sicher bei
mehreren gleichzeitig startenden Pod-Replicas (replicas: 2), da Prisma
migrate deploy einen DB-seitigen Advisory-Lock nutzt. deployment.yaml
bekommt eine startupProbe (failureThreshold 30 x periodSeconds 10 = bis
zu 5 Min), damit liveness/readiness den Container waehrend der
Migration nicht neu starten. ARCHITECTURE.md entsprechend aktualisiert,
migrate-job.yaml entfernt.
This commit is contained in:
Nick Szaunig committed 2026-08-26 22:33:44 +02:00
1 parent a6e5b0331f
commit 76a9e9c3a4
4 files changed
+18 -31

No files matched your search

+1 -1
View File
@@ -105,7 +105,7 @@ Fachliche Annahmen, getroffen weil das Lastenheft an der Stelle keine eindeutige
## 8. Backup & Restore
**Schema-Migrationen (Reproduzierbarkeit):** Ausschließlich `prisma/migrations/` als Quelle der Wahrheit. Lokal/Entwicklung: `npx prisma migrate dev`. Gegen jede Produktions- oder Staging-Datenbank ausschließlich `npx prisma migrate deploy` (idempotent, wendet nur fehlende Migrationen an, kein Schema-Drift). `prisma db push` wird an keiner Stelle im Code, in Skripten oder im Dockerfile verwendet und ist für Produktions-/Staging-Umgebungen untersagt. `migrate deploy` läuft als eigener Schritt vor dem Rollout, nicht im `CMD` des Runtime-Images, damit mehrere Pod-Replicas nicht gleichzeitig Migrationen ausführen: `deploy/k8s/backend/migrate-job.yaml` ist ein Kubernetes-`Job`, der dasselbe Backend-Image mit überschriebenem `command` (`npm run migrate:deploy`) nutzt – kein separates Migrations-Image. Reihenfolge und `kubectl`-Befehle stehen als Kommentar in der Datei.
**Schema-Migrationen (Reproduzierbarkeit):** Ausschließlich `prisma/migrations/` als Quelle der Wahrheit. Lokal/Entwicklung: `npx prisma migrate dev`. Gegen jede Produktions- oder Staging-Datenbank ausschließlich `npx prisma migrate deploy` (idempotent, wendet nur fehlende Migrationen an, kein Schema-Drift). `prisma db push` wird an keiner Stelle im Code, in Skripten oder im Dockerfile verwendet und ist für Produktions-/Staging-Umgebungen untersagt. Der Backend-Container führt `migrate deploy` selbst beim Start aus, bevor der Server Verbindungen annimmt (Dockerfile-`CMD`: `npm run migrate:deploy && node dist/main.js`) – kein separater Kubernetes-`Job`. Bei `replicas: 2` starten mehrere Pods potenziell gleichzeitig; das ist unproblematisch, da Prisma für `migrate deploy` einen datenbankseitigen Advisory-Lock nutzt – eine Instanz wendet die Migrationen an, die anderen warten kurz und finden danach nichts mehr zu tun. `deploy/k8s/backend/deployment.yaml` hat dafür eine `startupProbe` mit großzügigem `failureThreshold`, damit liveness/readiness den Container nicht neu starten, während die (beim allerersten Deploy ggf. länger laufende) Migration noch durchläuft.
**Datensicherung:** Seit der Entscheidung, PostgreSQL selbst im Cluster zu betreiben (siehe CLAUDE.md), liegt die Backup-Verantwortung bei diesem Projekt, nicht mehr bei einem externen Cluster-/DBA-Betrieb. Aktuell **noch nicht umgesetzt** (offener Punkt, siehe TASKS.md) – empfohlene Strategie:
+7 -4
View File
@@ -16,11 +16,14 @@ RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/generated ./generated
# schema.prisma, migrations/ und prisma.config.ts: noetig fuer
# `npm run migrate:deploy` (siehe deploy/k8s/backend/migrate-job.yaml), das
# dasselbe Image mit ueberschriebenem command nutzt statt eines eigenen
# Migrations-Images.
# `npm run migrate:deploy`, das der Container beim Start selbst ausfuehrt
# (siehe CMD unten), bevor der Server Verbindungen annimmt.
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/prisma.config.ts ./prisma.config.ts
EXPOSE 3001
USER node
CMD ["node", "dist/main.js"]
# migrate deploy ist idempotent und nutzt einen DB-seitigen Advisory-Lock,
# daher unproblematisch bei mehreren gleichzeitig startenden Pod-Replicas:
# eine Instanz wendet die Migrationen an, die anderen warten kurz und finden
# danach nichts mehr zu tun.
CMD ["sh", "-c", "npm run migrate:deploy && node dist/main.js"]
+10
View File
@@ -24,6 +24,16 @@ spec:
name: apicore-backend-config
- secretRef:
name: apicore-backend-secret
# Container fuehrt beim Start selbst `prisma migrate deploy` aus,
# bevor der Server Verbindungen annimmt (siehe Dockerfile CMD) -
# startupProbe gibt dafuer bis zu 5 Minuten Zeit, ohne dass
# liveness/readiness in der Zwischenzeit einen Neustart ausloesen.
startupProbe:
httpGet:
path: /health/ready
port: 3001
failureThreshold: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
-26
View File
@@ -1,26 +0,0 @@
# Job statt Teil des Deployment-CMD: laeuft einmalig vor dem Rollout, damit
# nicht mehrere Backend-Pod-Replicas gleichzeitig Migrationen ausfuehren
# (siehe ARCHITECTURE.md Abschnitt 8). Jobs sind unveraenderlich, daher vor
# jedem Deploy mit neuem Image-Tag zuerst loeschen:
#
# kubectl delete job apicore-backend-migrate --ignore-not-found
# kubectl apply -f deploy/k8s/backend/migrate-job.yaml
# kubectl wait --for=condition=complete job/apicore-backend-migrate --timeout=120s
# kubectl apply -f deploy/k8s/backend/deployment.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: apicore-backend-migrate
spec:
backoffLimit: 2
ttlSecondsAfterFinished: 3600
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: git.encry.de/nick.rosenloecher/apicore-backend:latest
command: ["npm", "run", "migrate:deploy"]
envFrom:
- secretRef:
name: apicore-backend-secret