version: '3.8' services: # Frontend service frontend: build: context: ./frontend dockerfile: Dockerfile restart: unless-stopped user: node ports: - "3000:3000" depends_on: - backend env_file: ./frontend/.env volumes: - ./logs:/app/logs:rw networks: - app-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: memory: 512M cpus: '0.5' # Backend API service backend: build: context: ./backend dockerfile: Dockerfile restart: unless-stopped user: node ports: - "4000:4000" depends_on: - mongodb - redis env_file: ./backend/.env volumes: - ./uploads:/app/uploads:rw - ./logs:/app/logs:rw networks: - app-network healthcheck: test: ["CMD", "curl", "-f", "http://localhost:4000/health"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: memory: 512M cpus: '0.5' # MongoDB service mongodb: image: mongo:7.0 restart: unless-stopped user: mongodb volumes: - mongo-data:/data/db:rw - ./mongo-init:/docker-entrypoint-initdb.d:ro networks: - app-network env_file: ./backend/.env environment: - MONGO_INITDB_ROOT_USERNAME=${MONGO_USER} - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} command: ["--auth", "--bind_ip_all", "--tlsMode", "preferTLS"] healthcheck: test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017 --quiet interval: 30s timeout: 10s retries: 3 deploy: resources: limits: memory: 1G cpus: '1.0' # Redis service redis: image: redis:alpine restart: unless-stopped command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"] volumes: - redis-data:/data:rw networks: - app-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: memory: 256M cpus: '0.2' # Nginx service for production nginx: image: nginx:alpine restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx/conf:/etc/nginx/conf.d:ro - ./nginx/ssl:/etc/nginx/ssl:ro - ./frontend/public:/var/www/html:ro depends_on: - frontend - backend networks: - app-network healthcheck: test: ["CMD", "curl", "-f", "https://localhost"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: memory: 128M cpus: '0.1' # Security scanner security_scanner: image: aquasec/trivy volumes: - /var/run/docker.sock:/var/run/docker.sock - ./security-reports:/reports command: ["image", "--format", "table", "--output", "/reports/scan-$(date +%Y%m%d).txt", "olathedeafclub-frontend:latest", "olathedeafclub-backend:latest"] profiles: - security # Networks with isolation networks: app-network: driver: bridge ipam: config: - subnet: 172.20.0.0/24 # Volumes with backup capability volumes: mongo-data: name: ocd-mongo-data redis-data: name: ocd-redis-data