# 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 # 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 ```