version: '3.8' # Docker Registry: registry.michaelschiemer.de (HTTPS via Traefik) services: # PHP-FPM Application Runtime app: image: registry.michaelschiemer.de/framework:latest container_name: app restart: unless-stopped networks: - app-internal environment: - TZ=Europe/Berlin - APP_ENV=${APP_ENV:-production} - APP_DEBUG=${APP_DEBUG:-false} - APP_URL=${APP_URL:-https://michaelschiemer.de} # Git Repository (optional - if set, container will clone/pull code on start) - GIT_REPOSITORY_URL=${GIT_REPOSITORY_URL:-} - GIT_BRANCH=${GIT_BRANCH:-main} - GIT_TOKEN=${GIT_TOKEN:-} - GIT_USERNAME=${GIT_USERNAME:-} - GIT_PASSWORD=${GIT_PASSWORD:-} # Database - DB_HOST=${DB_HOST:-postgres} - DB_PORT=${DB_PORT:-5432} - DB_DATABASE=${DB_DATABASE} - DB_USERNAME=${DB_USERNAME} - DB_PASSWORD=${DB_PASSWORD} # Redis - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD} # Cache - CACHE_DRIVER=redis - CACHE_PREFIX=${CACHE_PREFIX:-app} # Session - SESSION_DRIVER=redis - SESSION_LIFETIME=${SESSION_LIFETIME:-120} # Queue - QUEUE_DRIVER=redis - QUEUE_CONNECTION=default volumes: - app-storage:/var/www/html/storage - app-logs:/var/www/html/storage/logs - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro healthcheck: test: ["CMD-SHELL", "true"] interval: 30s timeout: 10s retries: 3 start_period: 40s depends_on: redis: condition: service_started # Nginx Web Server nginx: image: nginx:1.25-alpine container_name: nginx restart: unless-stopped networks: - traefik-public - app-internal environment: - TZ=Europe/Berlin volumes: - ./nginx/conf.d:/etc/nginx/conf.d:ro - app-code:/var/www/html:ro - app-storage:/var/www/html/storage:ro - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro labels: - "traefik.enable=true" # HTTP Router - "traefik.http.routers.app.rule=Host(`${APP_DOMAIN:-michaelschiemer.de}`)" - "traefik.http.routers.app.entrypoints=websecure" - "traefik.http.routers.app.tls=true" - "traefik.http.routers.app.tls.certresolver=letsencrypt" # Service - "traefik.http.services.app.loadbalancer.server.port=80" # Middleware - "traefik.http.routers.app.middlewares=default-chain@file" # Network - "traefik.docker.network=traefik-public" healthcheck: test: ["CMD-SHELL", "wget --spider -q http://127.0.0.1/health || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 10s depends_on: app: condition: service_started # Redis Cache/Session/Queue Backend redis: image: redis:7-alpine container_name: redis restart: unless-stopped networks: - app-internal environment: - TZ=Europe/Berlin command: > redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 512mb --maxmemory-policy allkeys-lru --save 900 1 --save 300 10 --save 60 10000 --appendonly yes --appendfsync everysec volumes: - redis-data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro healthcheck: test: ["CMD", "redis-cli", "--raw", "incr", "ping"] interval: 30s timeout: 10s retries: 3 start_period: 10s # Queue Worker (Background Jobs) queue-worker: image: registry.michaelschiemer.de/framework:latest container_name: queue-worker restart: unless-stopped networks: - app-internal environment: - TZ=Europe/Berlin - APP_ENV=${APP_ENV:-production} - APP_DEBUG=${APP_DEBUG:-false} # Database - DB_HOST=${DB_HOST:-postgres} - DB_PORT=${DB_PORT:-5432} - DB_DATABASE=${DB_DATABASE} - DB_USERNAME=${DB_USERNAME} - DB_PASSWORD=${DB_PASSWORD} # Redis - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD} # Queue - QUEUE_DRIVER=redis - QUEUE_CONNECTION=default - QUEUE_WORKER_SLEEP=${QUEUE_WORKER_SLEEP:-3} - QUEUE_WORKER_TRIES=${QUEUE_WORKER_TRIES:-3} - QUEUE_WORKER_TIMEOUT=${QUEUE_WORKER_TIMEOUT:-60} volumes: - app-storage:/var/www/html/storage - app-logs:/var/www/html/storage/logs - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro command: php console.php queue:work --queue=default --timeout=${QUEUE_WORKER_TIMEOUT:-60} 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 depends_on: app: condition: service_started redis: condition: service_started # Scheduler (Cron Jobs) scheduler: image: registry.michaelschiemer.de/framework:latest container_name: scheduler restart: unless-stopped networks: - app-internal environment: - TZ=Europe/Berlin - APP_ENV=${APP_ENV:-production} - APP_DEBUG=${APP_DEBUG:-false} # Database - DB_HOST=${DB_HOST:-postgres} - DB_PORT=${DB_PORT:-5432} - DB_DATABASE=${DB_DATABASE} - DB_USERNAME=${DB_USERNAME} - DB_PASSWORD=${DB_PASSWORD} # Redis - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD} volumes: - app-storage:/var/www/html/storage - app-logs:/var/www/html/storage/logs - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro command: php console.php scheduler:run 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 depends_on: app: condition: service_started redis: condition: service_started volumes: app-code: name: app-code app-storage: name: app-storage app-logs: name: app-logs redis-data: name: redis-data networks: traefik-public: external: true app-internal: external: true name: app-internal