services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: saas-postgres environment: POSTGRES_DB: ${POSTGRES_DB:-saas_db} POSTGRES_USER: ${POSTGRES_USER:-saas_user} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-secure_password_change_me} POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256" volumes: - postgres_data:/var/lib/postgresql/data - ./database/init:/docker-entrypoint-initdb.d ports: - "${POSTGRES_PORT:-5432}:5432" networks: - saas-network restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-saas_user} -d ${POSTGRES_DB:-saas_db}"] interval: 30s timeout: 10s retries: 3 # Redis for caching and sessions redis: image: redis:7-alpine container_name: saas-redis command: redis-server --requirepass ${REDIS_PASSWORD:-redis_secure_password_change_me} ports: - "${REDIS_PORT:-6379}:6379" volumes: - redis_data:/data networks: - saas-network restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "--raw", "incr", "ping"] interval: 30s timeout: 10s retries: 3 # API Gateway (Nginx) api-gateway: image: nginx:alpine container_name: saas-gateway ports: - "${HTTP_PORT:-80}:80" - "${HTTPS_PORT:-443}:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/conf.d:/etc/nginx/conf.d - ./ssl:/etc/nginx/ssl - ./apps/hello-world:/usr/share/nginx/html/hello-world networks: - saas-network depends_on: - postgres - redis - auth-service - api-service - dashboard - realtime-service restart: unless-stopped # Authentication Service auth-service: build: context: ./services/auth dockerfile: Dockerfile container_name: saas-auth environment: DATABASE_URL: postgresql://${POSTGRES_USER:-saas_user}:${POSTGRES_PASSWORD:-secure_password_change_me}@postgres:5432/${POSTGRES_DB:-saas_db} REDIS_URL: redis://:${REDIS_PASSWORD:-redis_secure_password_change_me}@redis:6379 JWT_SECRET: ${JWT_SECRET:-your_jwt_secret_change_me} NODE_ENV: development ports: - "3001:3001" volumes: - ./services/auth:/app - /app/node_modules networks: - saas-network depends_on: - postgres - redis restart: unless-stopped # API Service (Core API) api-service: build: context: . dockerfile: services/api/Dockerfile container_name: saas-api environment: DATABASE_URL: postgresql://${POSTGRES_USER:-saas_user}:${POSTGRES_PASSWORD:-secure_password_change_me}@postgres:5432/${POSTGRES_DB:-saas_db} REDIS_URL: redis://:${REDIS_PASSWORD:-redis_secure_password_change_me}@redis:6379 AUTH_SERVICE_URL: http://auth-service:3001 NODE_ENV: development ports: - "3000:3000" volumes: - ./services/api:/app - /app/node_modules - ./apps:/apps - /var/run/docker.sock:/var/run/docker.sock networks: - saas-network depends_on: - postgres - redis - auth-service restart: unless-stopped privileged: true # Storage Service (MinIO for S3-compatible storage) storage: image: minio/minio:latest container_name: saas-storage environment: MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin_change_me} ports: - "9000:9000" - "9001:9001" volumes: - minio_data:/data networks: - saas-network command: server /data --console-address ":9001" restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 # Real-time Service (WebSocket support) realtime-service: build: context: ./services/realtime dockerfile: Dockerfile container_name: saas-realtime environment: REDIS_URL: redis://:${REDIS_PASSWORD:-redis_secure_password_change_me}@redis:6379 JWT_SECRET: ${JWT_SECRET:-your_jwt_secret_change_me} PORT: 3002 NODE_ENV: development ports: - "3002:3002" volumes: - ./services/realtime:/app - /app/node_modules networks: - saas-network depends_on: - redis restart: unless-stopped # Monitoring (Prometheus) prometheus: image: prom/prometheus:latest container_name: saas-prometheus ports: - "9090:9090" volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus networks: - saas-network restart: unless-stopped # Monitoring (Grafana) grafana: image: grafana/grafana:latest container_name: saas-grafana environment: GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin_password_change_me} ports: - "3003:3000" volumes: - grafana_data:/var/lib/grafana - ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards - ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources networks: - saas-network depends_on: - prometheus restart: unless-stopped # MCP Server mcp-server: build: context: ./mcp-server dockerfile: Dockerfile container_name: saas-mcp-server environment: SAAS_API_URL: http://api-gateway SAAS_AUTH_URL: http://auth-service/auth SAAS_STORAGE_URL: http://storage/storage DEBUG: "false" volumes: - ./mcp-server:/app - /app/node_modules networks: - saas-network depends_on: - api-gateway - auth-service - storage restart: unless-stopped profiles: - mcp # Dashboard (React Admin Panel) dashboard: build: context: ./dashboard dockerfile: Dockerfile container_name: saas-dashboard ports: - "5173:80" volumes: - ./dashboard:/app - /app/node_modules networks: - saas-network depends_on: - api-service - auth-service restart: unless-stopped environment: - VITE_API_URL=http://localhost:8888/api - VITE_AUTH_API_URL=http://localhost:8888/auth - VITE_STORAGE_URL=http://localhost:8888/storage volumes: postgres_data: redis_data: minio_data: prometheus_data: grafana_data: networks: saas-network: driver: bridge