version: '3.9' services: # ─── Nginx Web Server ─────────────────────────────────────────────── nginx: image: nginx:1.27-alpine container_name: infra-nginx restart: unless-stopped ports: - "${APP_PORT:-8080}:80" - "${APP_HTTPS_PORT:-8443}:443" volumes: - .:/var/www/html:ro - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro - ./docker/nginx/ssl:/etc/nginx/ssl:ro - nginx_logs:/var/log/nginx depends_on: - php networks: - infra_network # ─── PHP-FPM Application ──────────────────────────────────────────── php: build: context: . dockerfile: docker/php/Dockerfile args: USER_ID: ${USER_ID:-1000} GROUP_ID: ${GROUP_ID:-1000} container_name: infra-php restart: unless-stopped volumes: - .:/var/www/html - ./storage:/var/www/html/storage - ./database:/var/www/html/database - php_logs:/var/log/supervisor environment: - APP_ENV=${APP_ENV:-local} - APP_DEBUG=${APP_DEBUG:-true} depends_on: redis: condition: service_healthy networks: - infra_network # ─── Redis Cache & Queue ───────────────────────────────────────────── redis: image: redis:7.4-alpine container_name: infra-redis restart: unless-stopped command: redis-server --requirepass ${REDIS_PASSWORD:-infra_redis_secret} --maxmemory 256mb --maxmemory-policy allkeys-lru ports: - "${REDIS_PORT:-6379}:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-infra_redis_secret}", "ping"] interval: 5s timeout: 3s retries: 5 networks: - infra_network # ─── Vite Dev Server (dev only) ────────────────────────────────────── vite: image: node:22-alpine container_name: infra-vite restart: unless-stopped working_dir: /var/www/html command: sh -c "npm install && npm run dev" volumes: - .:/var/www/html ports: - "5173:5173" networks: - infra_network profiles: - dev # ─── MySQL (optional - for production upgrade) ──────────────────────── mysql: image: mysql:8.0 container_name: infra-mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root_secret} MYSQL_DATABASE: ${MYSQL_DATABASE:-infra_manager} MYSQL_USER: ${MYSQL_USER:-infra_user} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-infra_secret} ports: - "${MYSQL_PORT:-3306}:3306" volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-root_secret}"] interval: 10s timeout: 5s retries: 5 networks: - infra_network profiles: - mysql volumes: redis_data: driver: local mysql_data: driver: local nginx_logs: driver: local php_logs: driver: local networks: infra_network: driver: bridge ipam: config: - subnet: 172.20.0.0/16