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
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:
@@ -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
|
||||
|
||||
493
deployment/docs/reference/docker-compose-production.md
Normal file
493
deployment/docs/reference/docker-compose-production.md
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user