version: '3.8' services: # ============================================================ # PostgreSQL + PostGIS # ============================================================ postgres: image: postgis/postgis:15-3.3 container_name: quixzoom-postgres environment: POSTGRES_DB: quixzoom POSTGRES_USER: quixzoom POSTGRES_PASSWORD: ${DB_PASSWORD:-quixzoom_secure_2026} volumes: - postgres_data:/var/lib/postgresql/data - ./persistence/postgres-schema.sql:/docker-entrypoint-initdb.d/01-schema.sql ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U quixzoom -d quixzoom"] interval: 10s timeout: 5s retries: 5 networks: - quixzoom-network # ============================================================ # Neo4j # ============================================================ neo4j: image: neo4j:5.13-community container_name: quixzoom-neo4j environment: NEO4J_AUTH: neo4j/${NEO4J_PASSWORD:-quixzoom_neo4j_2026} NEO4J_PLUGINS: '["apoc", "gds"]' NEO4J_dbms_memory_heap_initial__size: 512m NEO4J_dbms_memory_heap_max__size: 1G volumes: - neo4j_data:/data - neo4j_logs:/logs - ./persistence/neo4j-schema.cypher:/init/neo4j-schema.cypher ports: - "7474:7474" - "7687:7687" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7474"] interval: 10s timeout: 5s retries: 5 networks: - quixzoom-network # ============================================================ # Redis (caching, sessions, real-time) # ============================================================ redis: image: redis:7-alpine container_name: quixzoom-redis command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redis_data:/data ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - quixzoom-network # ============================================================ # QUIXZOOM API Server # ============================================================ api: build: context: . dockerfile: Dockerfile.api container_name: quixzoom-api environment: NODE_ENV: production PORT: 3000 DB_HOST: postgres DB_PORT: 5432 DB_NAME: quixzoom DB_USER: quixzoom DB_PASSWORD: ${DB_PASSWORD:-quixzoom_secure_2026} NEO4J_URI: bolt://neo4j:7687 NEO4J_USER: neo4j NEO4J_PASSWORD: ${NEO4J_PASSWORD:-quixzoom_neo4j_2026} REDIS_URL: redis://redis:6379 R2_BUCKET: ${R2_BUCKET} R2_ACCESS_KEY: ${R2_ACCESS_KEY} R2_SECRET_KEY: ${R2_SECRET_KEY} R2_ENDPOINT: ${R2_ENDPOINT} JWT_SECRET: ${JWT_SECRET:-quixzoom_jwt_secret_2026} ports: - "3000:3000" depends_on: postgres: condition: service_healthy neo4j: condition: service_healthy redis: condition: service_healthy volumes: - ./uploads:/app/uploads networks: - quixzoom-network restart: unless-stopped # ============================================================ # WebSocket Server # ============================================================ websocket: build: context: . dockerfile: Dockerfile.websocket container_name: quixzoom-websocket environment: NODE_ENV: production PORT: 8080 REDIS_URL: redis://redis:6379 API_URL: http://api:3000 ports: - "8080:8080" depends_on: - redis - api networks: - quixzoom-network restart: unless-stopped # ============================================================ # AI Workers # ============================================================ workers: build: context: . dockerfile: Dockerfile.workers container_name: quixzoom-workers environment: NODE_ENV: production DB_HOST: postgres DB_PORT: 5432 DB_NAME: quixzoom DB_USER: quixzoom DB_PASSWORD: ${DB_PASSWORD:-quixzoom_secure_2026} NEO4J_URI: bolt://neo4j:7687 NEO4J_USER: neo4j NEO4J_PASSWORD: ${NEO4J_PASSWORD:-quixzoom_neo4j_2026} REDIS_URL: redis://redis:6379 R2_BUCKET: ${R2_BUCKET} R2_ACCESS_KEY: ${R2_ACCESS_KEY} R2_SECRET_KEY: ${R2_SECRET_KEY} R2_ENDPOINT: ${R2_ENDPOINT} depends_on: postgres: condition: service_healthy neo4j: condition: service_healthy redis: condition: service_healthy networks: - quixzoom-network restart: unless-stopped # ============================================================ # Nginx Reverse Proxy # ============================================================ nginx: image: nginx:alpine container_name: quixzoom-nginx ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/ssl:/etc/nginx/ssl depends_on: - api - websocket networks: - quixzoom-network restart: unless-stopped volumes: postgres_data: neo4j_data: neo4j_logs: redis_data: networks: quixzoom-network: driver: bridge