253 lines
5.9 KiB
Markdown
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
|
|
```
|