- 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
10 KiB
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 - Detaillierter Deployment-Ablauf
- Initial Deployment Guide - Schritt-für-Schritt Anleitung
- Troubleshooting Guide - Häufige Probleme und Lösungen
Verwendung
# 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:
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:
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:
# security_opt:
# - no-new-privileges:true # ← Kommentiert
PHP Container:
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):
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):
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
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:
- Docker Secrets werden in
/run/secrets/<secret-name>gemountet - Framework liest automatisch
*_FILEVariablen und lädt den Inhalt - Secrets werden nie als Environment Variables exponiert
Siehe auch: Application Stack Deployment - Secret Handling
Entrypoint Overrides
Queue Worker
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
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 - Container Entrypoint Override
Health Checks
Web Container
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost/health"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
Funktionsweise:
- Prüft
/healthEndpoint via HTTPS - Startet nach 30 Sekunden (Container Startup Time)
- Prüft alle 15 Sekunden
- 5 Retries bei Fehlschlag
PHP Container
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
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.phpExistenz - Längeres Interval (60s) da Scheduler weniger kritisch
Volume Mounts
Application Code
volumes:
- /home/deploy/michaelschiemer/current:/var/www/html:rw
Wichtig:
- Absoluter Pfad auf dem Host
- Read-Write für
storage/undvar/Verzeichnisse - Code wird via
rsyncodergitsynchronisiert
Siehe auch: Code Deployment Workflow
Certbot Volumes
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
deploy:
resources:
limits:
memory: 512M
cpus: '1.0'
reservations:
memory: 256M
cpus: '0.5'
Grund: Nginx ist leichtgewichtig, benötigt wenig Ressourcen.
PHP Container
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
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
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
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
restart: always
Funktionsweise:
- Container wird automatisch neu gestartet bei:
- Container Exit (auch bei Fehlern)
- Docker Daemon Restart
- System Reboot
Alternative Policies:
no: Kein automatischer Restarton-failure: Nur bei Fehlernunless-stopped: Immer, außer manuell gestoppt
Dependencies
Service Dependencies
depends_on:
php:
condition: service_healthy
certbot:
condition: service_started
Funktionsweise:
service_healthy: Wartet auf erfolgreichen Health Checkservice_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
# 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
# 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
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:
env_file:
- /home/deploy/deployment/stacks/production/.env
❌ Falsch:
env_file:
- .env # Relativer Pfad - funktioniert nur im richtigen Verzeichnis
2. Entrypoint Override für CLI-Container
✅ Richtig:
queue-worker:
entrypoint: ""
command: ["php", "/var/www/html/worker.php"]
❌ Falsch:
queue-worker:
# Kein Entrypoint Override - startet PHP-FPM/Nginx unnötig
3. Capabilities für PHP-FPM
✅ Richtig:
web:
cap_add:
- SETGID
- SETUID
❌ Falsch:
web:
security_opt:
- no-new-privileges:true # Verhindert PHP-FPM User Switching
Troubleshooting
Problem: Container startet nicht / unhealthy
Lösung: Siehe Troubleshooting Guide
Häufige Ursachen:
- Missing Environment Variables →
env_filemit 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:
env_file:
- /home/deploy/deployment/stacks/production/.env
Problem: Queue Worker startet PHP-FPM
Ursache: Entrypoint Override fehlt
Lösung:
queue-worker:
entrypoint: ""
command: ["php", "/var/www/html/worker.php"]
Referenz
- Application Stack Deployment - Detaillierter Ablauf
- Initial Deployment Guide - Schritt-für-Schritt Anleitung
- Troubleshooting Guide - Probleme und Lösungen
- Code Deployment Workflow - Code-Synchronisation