226 lines
6.2 KiB
YAML
226 lines
6.2 KiB
YAML
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
|