Files
2026-08-03 13:38:11 +02:00

253 lines
5.9 KiB
Markdown

# Deployment & CI/CD Guide
## 1. Docker Development Cycle
Der empfohlene Entwicklungs-Workflow nutzt Docker Compose für eine isolierte Umgebung mit Hot-Reload.
### Voraussetzungen
- Docker (v20.10+)
- Docker Compose (v2.0+)
### Ersts Start (Build & Initialize)
```bash
# Navigiere zum Projektverzeichnis
cd formeleon
# Build Images und Start Container
docker-compose up --build
```
Das Entrypoint-Script führt automatisch folgende Schritte aus:
1. Prüft Python-Abhängigkeiten
2. Führt Datenbank-Migrationen aus (`flask db upgrade`)
3. Seeded die Datenbank mit Testdaten (`flask seed-db`) - nur bei leerer DB
4. Startet den Flask-Entwicklungsserver mit Hot-Reload
### Täglicher Entwicklungs-Workflow
#### Container starten/stoppen
```bash
# Starten (im Hintergrund)
docker-compose up -d
# Stoppen
docker-compose down
# Neu starten (nach Code-Änderungen)
docker-compose restart app
# Logs anzeigen
docker-compose logs -f app
```
#### Code-Änderungen testen
Dank der Volume-Mounts in `docker-compose.yml` werden Änderungen an folgenden Verzeichnissen sofort im Container sichtbar:
- `app.py`, `config.py`, `models.py`
- `routes/`
- `services/`
- `utils/`
- `templates/`
- `static/`
- `migrations/`
**Kein Container-Rebuild nötig!** Der Flask-Dev-Server erkennt Änderungen und lädt neu.
### Flask CLI-Kommandos in Docker
Führe Flask-Kommandos im laufenden Container aus:
```bash
# Allgemeine Syntax
docker-compose run --rm app flask <kommando>
# Beispiele:
# Migration erstellen
docker-compose run --rm app flask db migrate -m "add user table"
# Migration anwenden
docker-compose run --rm app flask db upgrade
# Migration zurücksetzen
docker-compose run --rm app flask db downgrade
# Datenbank mit Testdaten füllen
docker-compose run --rm app flask seed-db
# Mandanten verwalten
docker-compose run --rm app flask create-tenant "Test" "public-key-123"
# Benutzer verwalten
docker-compose run --rm app flask create-user "test@example.com" "Test User" --role=admin
```
### Shell im Container
```bash
# Interaktive Shell
docker-compose exec app bash
# Python Shell
docker-compose exec app python
# Flask Shell (mit App-Kontext)
docker-compose exec app flask shell
```
### Datenbank zurücksetzen
```bash
# Container stoppen und Volumes löschen (ACHTUNG: Alle Daten gehen verloren!)
docker-compose down -v
# Neu starten mit frischer Datenbank
docker-compose up --build
```
---
## 2. Docker Setup für Produktion
Für die Produktion sollte ein separates `docker-compose.prod.yml` erstellt werden.
### `docker-compose.prod.yml` (Beispiel)
```yaml
version: '3.8'
services:
web:
build: .
container_name: formeleon-web
ports:
- "8000:5000"
environment:
- FLASK_ENV=production
- FLASK_DEBUG=0
- DEV_MODE=false
- SECRET_KEY=${SECRET_KEY}
- SQLALCHEMY_DATABASE_URI=${DATABASE_URL}
- ZITADEL_ISSUER=${ZITADEL_ISSUER}
- ZITADEL_CLIENT_ID=${ZITADEL_CLIENT_ID}
- ZITADEL_CLIENT_SECRET=${ZITADEL_CLIENT_SECRET}
- RECAPTCHA_SITE_KEY=${RECAPTCHA_SITE_KEY}
- RECAPTCHA_SECRET_KEY=${RECAPTCHA_SECRET_KEY}
volumes:
- ./data:/app/data
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/"]
interval: 30s
timeout: 10s
retries: 3
postgres:
image: postgres:15-alpine
container_name: formeleon-postgres
environment:
- POSTGRES_DB=formeleon
- POSTGRES_USER=formeleon
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U formeleon"]
interval: 5s
timeout: 5s
retries: 5
volumes:
postgres_data:
```
### Produktion starten
```bash
# Mit kombinierter Konfiguration
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
# Logs anzeigen
docker-compose logs -f
# Status prüfen
docker-compose ps
```
---
## 3. Gitea Actions Workflow
Bei einem Push auf den `main`-Branch oder einem Release-Tag führt der Gitea-Runner automatisiert folgende Schritte auf dem Zielserver aus:
1. Code-Update via `git pull`.
2. Erstellen/Aktualisieren der Docker-Images.
3. Zero-Downtime Restart der Container via Docker Compose.
### Beispiel `.gitea/workflows/deploy.yml`
```yaml
name: Deploy to Production
on:
push:
branches: [main]
tags: ['v*']
jobs:
deploy:
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Stop services
run: docker-compose -f docker-compose.yml -f docker-compose.prod.yml down
- name: Pull latest images
run: docker-compose -f docker-compose.yml -f docker-compose.prod.yml pull
- name: Build and start
run: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build
- name: Run migrations
run: docker-compose -f docker-compose.yml -f docker-compose.prod.yml run --rm web flask db upgrade
- name: Cleanup
run: docker system prune -f
```
---
## 4. Docker Troubleshooting
### Häufige Probleme & Lösungen
| Problem | Lösung |
|---------|--------|
| Port 5000 bereits belegt | `docker-compose down` und neu starten |
| Datenbank-Fehler | `docker-compose down -v && docker-compose up --build` |
| Python-Module nicht gefunden | `docker-compose build --no-cache && docker-compose up` |
| Container startet nicht | `docker-compose logs app` prüfen |
| Hot-Reload funktioniert nicht | Volume-Mounts in docker-compose.yml prüfen |
### Debug-Modus
```bash
# Container im Debug-Modus starten
docker-compose up --build --abort-on-container-exit
# Oder mit Shell
ENTERPOINT_OVERRIDE=bash docker-compose run --rm --service-ports app
```
### Cache leeren
```bash
# Docker Cache leeren
docker builder prune
# Unused Images entfernen
docker image prune -a
# System cleanup
docker system prune -a --volumes
```