# Production Overrides for docker-compose.yml # Usage: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d services: # ============================================================================== # Web - Production Overrides # ============================================================================== web: image: 94.16.110.151:5000/framework:latest pull_policy: always # Always pull from registry, never build # entrypoint.sh from image is used (starts PHP-FPM + nginx) user: root # Run as root for nginx/php-fpm management ports: - "8888:80" - "8443:443" volumes: # Production: Only mount persistent data subdirectories # Source code is embedded in Docker image - ./storage/logs:/var/www/html/storage/logs:rw - ./storage/uploads:/var/www/html/storage/uploads:rw - ./ssl:/var/www/ssl:ro # Named volumes for cache and other runtime data - storage-cache:/var/www/html/storage/cache:rw - storage-queue:/var/www/html/storage/queue:rw - var-data:/var/www/html/var:rw networks: - backend environment: - APP_ENV=production healthcheck: # Use curl (available in production image) test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s labels: com.centurylinklabs.watchtower.enable: "true" # ============================================================================== # PHP - Production Overrides # ============================================================================== php: image: 94.16.110.151:5000/framework:latest user: root # Override base user - production image runs supervisor as root volumes: # Minimal volumes for production - ./storage/logs:/var/www/html/storage/logs:rw - ./storage/uploads:/var/www/html/storage/uploads:rw - storage-cache:/var/www/html/storage/cache:rw - storage-queue:/var/www/html/storage/queue:rw - var-data:/var/www/html/var:rw environment: APP_ENV: production APP_DEBUG: "false" XDEBUG_MODE: "off" # No Xdebug in production labels: com.centurylinklabs.watchtower.enable: "true" # ============================================================================== # Database - Production Config # ============================================================================== db: volumes: # Override volumes completely to exclude config files - db_data:/var/lib/postgresql/data # ============================================================================== # Redis - Production Config # ============================================================================== redis: volumes: - ./docker/redis/redis-secure.conf:/usr/local/etc/redis/redis.conf:ro - redis_data:/data # ============================================================================== # Queue Worker - Production # ============================================================================== queue-worker: image: 94.16.110.151:5000/framework:latest user: root # Override base user - production image runs supervisor as root environment: - APP_ENV=production - WORKER_DEBUG=false labels: com.centurylinklabs.watchtower.enable: "true" # ============================================================================== # Watchtower - Auto-Update # ============================================================================== watchtower: image: containrrr/watchtower:latest container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock environment: WATCHTOWER_CLEANUP: "true" WATCHTOWER_POLL_INTERVAL: 300 # Check every 5 minutes WATCHTOWER_LABEL_ENABLE: "true" WATCHTOWER_INCLUDE_STOPPED: "false" WATCHTOWER_REVIVE_STOPPED: "false" WATCHTOWER_NOTIFICATIONS: "shoutrrr" WATCHTOWER_NOTIFICATION_URL: "${WATCHTOWER_NOTIFICATION_URL:-}" command: --interval 300 --cleanup --label-enable networks: - backend # ============================================================================== # Prometheus - Monitoring (VPN-only) # ============================================================================== prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - "10.8.0.1:9090:9090" # VPN-only volumes: - ./monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' networks: - backend # ============================================================================== # Grafana - Visualization (VPN-only) # ============================================================================== grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - "10.8.0.1:3000:3000" # VPN-only environment: GF_SECURITY_ADMIN_USER: ${GRAFANA_USER:-admin} GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD} GF_INSTALL_PLUGINS: "" volumes: - grafana-data:/var/lib/grafana - ./monitoring/grafana/provisioning:/etc/grafana/provisioning:ro depends_on: - prometheus networks: - backend # ============================================================================== # Portainer - Container Management (VPN-only) # ============================================================================== portainer: image: portainer/portainer-ce:latest container_name: portainer restart: unless-stopped ports: - "10.8.0.1:9443:9443" # VPN-only HTTPS volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer-data:/data networks: - backend # ============================================================================== # Production Networks # ============================================================================== networks: backend: driver: bridge # ============================================================================== # Production Volumes # ============================================================================== volumes: storage-cache: storage-queue: var-data: db_data: redis_data: prometheus-data: grafana-data: portainer-data: