fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled

- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

View File

@@ -2,16 +2,40 @@
## Übersicht
Dieses Dokument erklärt, wie genau das Deployment in den Application Stack abläuft, wenn die CI/CD Pipeline ausgeführt wird.
Dieses Dokument erklärt, wie genau das Deployment in den Application Stack abläuft. Es gibt zwei Deployment-Szenarien:
1. **Initial Deployment** - Erstes Setup des Servers (Rsync-basiert)
2. **Normal Deployment** - Regelmäßige Deployments via CI/CD (Git-basiert)
**📖 Verwandte Dokumentation:**
- **[Initial Deployment Guide](../guides/initial-deployment-guide.md)** - Schritt-für-Schritt Initial Deployment
- **[Code Deployment Workflow](../guides/code-deployment-workflow.md)** - Unterschiede zwischen Rsync und Git
- **[Code Changes Workflow](../guides/code-change-workflow.md)** - Wie Codeänderungen gepusht werden
- **[CI/CD Status](../status/ci-cd-status.md)** - Aktueller Status der Pipeline
- **[Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)** - Häufige Probleme und Lösungen
---
## Deployment-Flow
### Initial Deployment (Rsync-basiert)
```
Local Repository
1. Code Sync via rsync (sync-application-code.yml)
2. Composer Dependencies installieren (install-composer-dependencies.yml)
3. Docker Image Build & Push (build-initial-image.yml)
4. Application Stack deployen (setup-infrastructure.yml)
5. Container starten und verifizieren
```
### Normal Deployment (Git-basiert / CI/CD)
```
CI/CD Pipeline (Gitea Actions)
@@ -19,9 +43,11 @@ CI/CD Pipeline (Gitea Actions)
2. Docker Image Build & Push zur Registry
3. Ansible Playbook ausführen
3. Code deployen via Git (deploy-application-code.yml)
4. Application Stack aktualisieren
4. Ansible Playbook ausführen (deploy-update.yml)
5. Application Stack aktualisieren
```
### Secret Handling für Redis
@@ -30,7 +56,7 @@ CI/CD Pipeline (Gitea Actions)
unter dem Schlüssel `vault_redis_password`.
- Die Application-Rolle (`roles/application/tasks/sync.yml`) bricht den Deploy ab,
wenn kein Passwort aus dem Vault oder via `-e redis_password=...` vorhanden ist.
- Während des Deployments wird das Passwort in `stacks/application/.env` geschrieben
- Während des Deployments wird das Passwort in `stacks/production/.env` geschrieben
und steht damit allen PHP-Containern über `REDIS_PASSWORD` zur Verfügung.
- Docker Secrets mit `REDIS_PASSWORD_FILE` werden weiterhin unterstützt, da der
Entry-Point das Secret lädt bevor PHP-FPM startet.
@@ -117,7 +143,7 @@ Das Ansible Playbook führt folgende Schritte auf dem Production-Server aus:
**3. Verzeichnisse erstellen**
```yaml
- Application Stack Path: ~/deployment/stacks/application
- Application Stack Path: ~/deployment/stacks/production
- Backup Verzeichnis: ~/deployment/backups/<timestamp>/
```
@@ -387,7 +413,7 @@ docker pull registry.michaelschiemer.de/framework:abc1234-1696234567
# Nachher: image: registry.michaelschiemer.de/framework:abc1234-1696234567
# 5. Stack neu starten
cd ~/deployment/stacks/application
cd ~/deployment/stacks/production
docker compose up -d --pull always --force-recreate --remove-orphans
# 6. Health-Checks warten
@@ -526,7 +552,7 @@ ansible-playbook -i inventory/production.yml \
```bash
# Logs prüfen
docker compose -f ~/deployment/stacks/application/docker-compose.yml logs
docker compose -f ~/deployment/stacks/production/docker-compose.yml logs
# Health-Check-Status prüfen
docker compose ps

View File

@@ -0,0 +1,493 @@
# Docker Compose Production Configuration
**Stand:** 2025-11-07
**Status:** Vollständige Dokumentation der Production-Konfiguration
---
## Übersicht
Dieses Dokument erklärt die Production-spezifische Docker Compose Konfiguration (`docker-compose.production.yml`). Diese Datei überschreibt die Basis-Konfiguration (`docker-compose.base.yml`) mit Production-spezifischen Einstellungen.
**📖 Verwandte Dokumentation:**
- [Application Stack Deployment](./application-stack.md) - Detaillierter Deployment-Ablauf
- [Initial Deployment Guide](../guides/initial-deployment-guide.md) - Schritt-für-Schritt Anleitung
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Häufige Probleme und Lösungen
---
## Verwendung
```bash
# Production Stack starten
docker compose -f docker-compose.base.yml -f docker-compose.production.yml up -d
# Mit .env Datei
docker compose -f docker-compose.base.yml -f docker-compose.production.yml --env-file .env up -d
```
**Wichtig:** Die Production-Konfiguration wird immer zusammen mit der Basis-Konfiguration verwendet.
---
## Security Settings
### Capabilities
**Web Container:**
```yaml
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- NET_BIND_SERVICE # Required for binding to ports 80/443
- SETGID # Required for PHP-FPM to switch to www-data
- SETUID # Required for PHP-FPM to switch to www-data
```
**PHP Container:**
```yaml
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
```
**Wichtig:** `SETGID` und `SETUID` sind für den `web` Container erforderlich, damit PHP-FPM zum `www-data` User (UID 33) wechseln kann.
**Trade-off:** `no-new-privileges: true` ist für den `web` Container **deaktiviert**, um PHP-FPM User Switching zu ermöglichen. Dies ist ein bewusster Security Trade-off.
### no-new-privileges
**Web Container:**
```yaml
# security_opt:
# - no-new-privileges:true # ← Kommentiert
```
**PHP Container:**
```yaml
security_opt:
- no-new-privileges:true # ← Aktiv
```
**Grund:** Der `web` Container benötigt Privilege Escalation für PHP-FPM, während der `php` Container nach dem User Switch (`gosu`) keine weiteren Privileges benötigt.
---
## Environment Variables
### env_file vs. environment
**env_file (Empfohlen):**
```yaml
env_file:
- /home/deploy/deployment/stacks/production/.env # ← Absoluter Pfad
```
**Wichtig:** **Immer absolute Pfade verwenden**, um sicherzustellen, dass die `.env` Datei gefunden wird, unabhängig vom Working Directory.
**environment (Override):**
```yaml
environment:
- APP_ENV=production
- APP_DEBUG=false
- PHP_MEMORY_LIMIT=512M
```
**Reihenfolge:** `env_file` wird zuerst geladen, dann werden `environment` Variablen als Override angewendet.
### Docker Secrets Integration
**Pattern:** `*_FILE` Environment Variables
```yaml
environment:
- DB_PASSWORD_FILE=/run/secrets/db_user_password
- REDIS_PASSWORD_FILE=/run/secrets/redis_password
- APP_KEY_FILE=/run/secrets/app_key
- VAULT_ENCRYPTION_KEY_FILE=/run/secrets/vault_encryption_key
secrets:
- db_user_password
- redis_password
- app_key
- vault_encryption_key
```
**Funktionsweise:**
1. Docker Secrets werden in `/run/secrets/<secret-name>` gemountet
2. Framework liest automatisch `*_FILE` Variablen und lädt den Inhalt
3. Secrets werden nie als Environment Variables exponiert
**Siehe auch:** [Application Stack Deployment](./application-stack.md) - Secret Handling
---
## Entrypoint Overrides
### Queue Worker
```yaml
queue-worker:
entrypoint: "" # ← Leerer Entrypoint überschreibt Image Entrypoint
command: ["php", "/var/www/html/worker.php"]
```
**Grund:** Der Image Entrypoint (`/usr/local/bin/entrypoint.sh`) startet PHP-FPM und Nginx. Der Queue Worker benötigt nur PHP CLI.
### Scheduler
```yaml
scheduler:
entrypoint: "" # ← Leerer Entrypoint überschreibt Image Entrypoint
command: php console.php scheduler:run
```
**Grund:** Gleicher Grund wie Queue Worker - nur PHP CLI erforderlich.
**Siehe auch:** [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Container Entrypoint Override
---
## Health Checks
### Web Container
```yaml
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost/health"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
```
**Funktionsweise:**
- Prüft `/health` Endpoint via HTTPS
- Startet nach 30 Sekunden (Container Startup Time)
- Prüft alle 15 Sekunden
- 5 Retries bei Fehlschlag
### PHP Container
```yaml
healthcheck:
test: ["CMD", "php", "-v"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
```
**Funktionsweise:**
- Prüft PHP Verfügbarkeit
- Einfacher Check für Container-Health
### Scheduler
```yaml
healthcheck:
test: ["CMD-SHELL", "php -r 'exit(0);' && test -f /var/www/html/console.php || exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
```
**Funktionsweise:**
- Prüft PHP Verfügbarkeit und `console.php` Existenz
- Längeres Interval (60s) da Scheduler weniger kritisch
---
## Volume Mounts
### Application Code
```yaml
volumes:
- /home/deploy/michaelschiemer/current:/var/www/html:rw
```
**Wichtig:**
- **Absoluter Pfad** auf dem Host
- **Read-Write** für `storage/` und `var/` Verzeichnisse
- Code wird via `rsync` oder `git` synchronisiert
**Siehe auch:** [Code Deployment Workflow](../guides/code-deployment-workflow.md)
### Certbot Volumes
```yaml
volumes:
- certbot-conf:/etc/letsencrypt:ro
- certbot-www:/var/www/certbot:ro
```
**Funktionsweise:**
- `certbot-conf`: SSL Zertifikate (Read-Only für Web Container)
- `certbot-www`: Webroot für Let's Encrypt Challenge
---
## Resource Limits
### Web Container
```yaml
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.5'
```
**Grund:** Nginx ist leichtgewichtig, benötigt wenig Ressourcen.
### PHP Container
```yaml
deploy:
resources:
limits:
memory: 1G
cpus: '2.0'
reservations:
memory: 512M
cpus: '1.0'
```
**Grund:** PHP-FPM benötigt mehr Ressourcen für Request-Verarbeitung.
### Queue Worker
```yaml
deploy:
resources:
limits:
memory: 2G
cpus: '2.0'
reservations:
memory: 1G
cpus: '1.0'
```
**Grund:** Queue Worker verarbeitet lange Jobs, benötigt mehr Memory.
### Scheduler
```yaml
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'
```
**Grund:** Scheduler läuft periodisch, benötigt wenig Ressourcen.
---
## Logging
### JSON Logging mit Rotation
```yaml
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
compress: "true"
labels: "service,environment"
```
**Funktionsweise:**
- **max-size:** Maximale Größe pro Log-Datei
- **max-file:** Anzahl der Log-Dateien (Rotation)
- **compress:** Komprimierung alter Log-Dateien
- **labels:** Metadaten für Log-Aggregation
**Beispiel:** Bei 5 Dateien à 10MB = max. 50MB Log-Speicher pro Container.
---
## Restart Policies
```yaml
restart: always
```
**Funktionsweise:**
- Container wird automatisch neu gestartet bei:
- Container Exit (auch bei Fehlern)
- Docker Daemon Restart
- System Reboot
**Alternative Policies:**
- `no`: Kein automatischer Restart
- `on-failure`: Nur bei Fehlern
- `unless-stopped`: Immer, außer manuell gestoppt
---
## Dependencies
### Service Dependencies
```yaml
depends_on:
php:
condition: service_healthy
certbot:
condition: service_started
```
**Funktionsweise:**
- `service_healthy`: Wartet auf erfolgreichen Health Check
- `service_started`: Wartet nur auf Container Start
**Wichtig:** `queue-worker` und `scheduler` warten auf `php` Container Health, da sie die gleiche Codebase verwenden.
---
## External Services
### PostgreSQL
```yaml
# Database service removed - using external PostgreSQL Stack
# Connection via app-internal network using docker-compose.postgres-override.yml
```
**Grund:** PostgreSQL läuft in separatem Stack (`deployment/stacks/postgresql/`) für bessere Isolation.
### Redis
```yaml
# Redis service removed - using external Redis Stack
# Connection via app-internal network using docker-compose.redis-override.yml
```
**Grund:** Redis läuft in separatem Stack (`deployment/stacks/redis/`) für bessere Isolation.
**Verbindung:** Via `app-internal` Network (siehe `docker-compose.base.yml`).
---
## Networks
### Cache Network
```yaml
networks:
cache:
internal: true # Cache network is internal in production
```
**Funktionsweise:**
- **Internal:** Keine externe Verbindung möglich
- Nur für Container-zu-Container Kommunikation
- Erhöht Security (Redis nicht von außen erreichbar)
---
## Best Practices
### 1. Absolute Pfade für env_file
**✅ Richtig:**
```yaml
env_file:
- /home/deploy/deployment/stacks/production/.env
```
**❌ Falsch:**
```yaml
env_file:
- .env # Relativer Pfad - funktioniert nur im richtigen Verzeichnis
```
### 2. Entrypoint Override für CLI-Container
**✅ Richtig:**
```yaml
queue-worker:
entrypoint: ""
command: ["php", "/var/www/html/worker.php"]
```
**❌ Falsch:**
```yaml
queue-worker:
# Kein Entrypoint Override - startet PHP-FPM/Nginx unnötig
```
### 3. Capabilities für PHP-FPM
**✅ Richtig:**
```yaml
web:
cap_add:
- SETGID
- SETUID
```
**❌ Falsch:**
```yaml
web:
security_opt:
- no-new-privileges:true # Verhindert PHP-FPM User Switching
```
---
## Troubleshooting
### Problem: Container startet nicht / unhealthy
**Lösung:** Siehe [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md)
**Häufige Ursachen:**
- Missing Environment Variables → `env_file` mit absolutem Pfad prüfen
- PHP-FPM Permission Errors → Capabilities (SETGID/SETUID) prüfen
- Missing Application Code → Code-Sync prüfen
### Problem: Environment Variables werden nicht geladen
**Ursache:** Relativer Pfad in `env_file`
**Lösung:** Absoluten Pfad verwenden:
```yaml
env_file:
- /home/deploy/deployment/stacks/production/.env
```
### Problem: Queue Worker startet PHP-FPM
**Ursache:** Entrypoint Override fehlt
**Lösung:**
```yaml
queue-worker:
entrypoint: ""
command: ["php", "/var/www/html/worker.php"]
```
---
## Referenz
- [Application Stack Deployment](./application-stack.md) - Detaillierter Ablauf
- [Initial Deployment Guide](../guides/initial-deployment-guide.md) - Schritt-für-Schritt Anleitung
- [Troubleshooting Guide](../troubleshooting/initial-deployment-issues.md) - Probleme und Lösungen
- [Code Deployment Workflow](../guides/code-deployment-workflow.md) - Code-Synchronisation