version: "3.9" networks: compliance-net: driver: bridge volumes: postgres_data: redis_data: milvus_data: minio_data: neo4j_data: neo4j_logs: services: # ═══════════════════════════════════════════════ # 基础数据层 # ═══════════════════════════════════════════════ postgres: image: pgvector/pgvector:pg16 container_name: compliance-postgres restart: unless-stopped environment: POSTGRES_USER: compliance POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-compliance123} POSTGRES_DB: compliance_db volumes: - postgres_data:/var/lib/postgresql/data - ./init-sql:/docker-entrypoint-initdb.d ports: - "5432:5432" networks: [compliance-net] healthcheck: test: ["CMD-SHELL", "pg_isready -U compliance -d compliance_db"] interval: 10s timeout: 5s retries: 10 redis: image: redis:7-alpine container_name: compliance-redis restart: unless-stopped command: > redis-server --requirepass ${REDIS_PASSWORD:-redis123} --maxmemory 2gb --maxmemory-policy allkeys-lru volumes: - redis_data:/data ports: - "6379:6379" networks: [compliance-net] healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-redis123}", "ping"] interval: 10s timeout: 5s retries: 5 # ═══════════════════════════════════════════════ # Milvus 向量数据库(Standalone,含 etcd + minio) # ═══════════════════════════════════════════════ etcd: image: quay.io/coreos/etcd:v3.5.5 container_name: milvus-etcd restart: unless-stopped environment: ETCD_AUTO_COMPACTION_MODE: revision ETCD_AUTO_COMPACTION_RETENTION: "1000" ETCD_QUOTA_BACKEND_BYTES: "4294967296" ETCD_SNAPSHOT_COUNT: "50000" volumes: - milvus_data:/etcd command: > etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls=http://0.0.0.0:2379 --data-dir=/etcd networks: [compliance-net] healthcheck: test: ["CMD", "etcdctl", "endpoint", "health"] interval: 30s timeout: 20s retries: 3 minio: image: minio/minio:RELEASE.2023-03-13T19-46-17Z container_name: milvus-minio restart: unless-stopped environment: MINIO_ACCESS_KEY: minioadmin MINIO_SECRET_KEY: minioadmin volumes: - minio_data:/minio_data command: minio server /minio_data --console-address ":9001" ports: - "9001:9001" # MinIO 控制台(可选访问) networks: [compliance-net] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 milvus: image: milvusdb/milvus:v2.4.13 container_name: compliance-milvus restart: unless-stopped command: ["milvus", "run", "standalone"] environment: ETCD_ENDPOINTS: etcd:2379 MINIO_ADDRESS: minio:9000 volumes: - milvus_data:/var/lib/milvus ports: - "19530:19530" # gRPC API - "9091:9091" # HTTP API depends_on: etcd: condition: service_healthy minio: condition: service_healthy networks: [compliance-net] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"] interval: 30s timeout: 20s retries: 10 start_period: 60s # ═══════════════════════════════════════════════ # Neo4j 知识图谱数据库 # ═══════════════════════════════════════════════ neo4j: image: neo4j:5.20-community container_name: compliance-neo4j restart: unless-stopped environment: NEO4J_AUTH: neo4j/${NEO4J_PASSWORD:-neo4j123} NEO4J_PLUGINS: '["apoc"]' NEO4J_dbms_security_procedures_unrestricted: apoc.* NEO4J_dbms_memory_heap_initial__size: 512m NEO4J_dbms_memory_heap_max__size: 2G NEO4J_dbms_memory_pagecache_size: 1G volumes: - neo4j_data:/data - neo4j_logs:/logs ports: - "7474:7474" # Browser UI - "7687:7687" # Bolt 协议 networks: [compliance-net] healthcheck: test: ["CMD-SHELL", "wget -q --spider http://localhost:7474 || exit 1"] interval: 30s timeout: 10s retries: 10 start_period: 60s # ═══════════════════════════════════════════════ # AI 模型服务 # ═══════════════════════════════════════════════ embedding-service: build: context: ./services/embedding dockerfile: Dockerfile image: compliance-embedding:latest container_name: compliance-embedding restart: unless-stopped environment: MODEL_NAME: BAAI/bge-m3 HF_ENDPOINT: ${HF_ENDPOINT:-https://hf-mirror.com} DEVICE: ${EMBEDDING_DEVICE:-cpu} MAX_BATCH_SIZE: "16" volumes: - ./models:/app/models ports: - "8010:8010" networks: [compliance-net] deploy: resources: limits: memory: 8G healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8010/health"] interval: 30s timeout: 10s retries: 5 start_period: 120s # 模型加载需要时间 mcp-server: build: context: ./services/mcp-server dockerfile: Dockerfile image: compliance-mcp:latest container_name: compliance-mcp restart: unless-stopped environment: DEVICE: ${MCP_DEVICE:-cpu} HF_ENDPOINT: ${HF_ENDPOINT:-https://hf-mirror.com} volumes: - ./models:/app/models - ./data/uploads:/app/uploads - ./data/parsed:/app/parsed ports: - "8011:8011" networks: [compliance-net] deploy: resources: limits: memory: 8G healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8011/health"] interval: 30s timeout: 10s retries: 5 start_period: 120s # ═══════════════════════════════════════════════ # 业务服务层 # ═══════════════════════════════════════════════ compliance-backend: build: context: ./services/compliance-backend dockerfile: Dockerfile image: compliance-backend:latest container_name: compliance-backend restart: unless-stopped env_file: .env environment: DATABASE_URL: postgresql+asyncpg://compliance:${POSTGRES_PASSWORD:-compliance123}@postgres:5432/compliance_db REDIS_URL: redis://:${REDIS_PASSWORD:-redis123}@redis:6379/0 MILVUS_HOST: milvus MILVUS_PORT: "19530" NEO4J_URI: bolt://neo4j:7687 NEO4J_USER: neo4j NEO4J_PASSWORD: ${NEO4J_PASSWORD:-neo4j123} EMBEDDING_SERVICE_URL: http://embedding-service:8010 MCP_SERVER_URL: http://mcp-server:8011 LLM_PROVIDER: ${LLM_PROVIDER:-deepseek} DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} DEEPSEEK_MODEL: ${DEEPSEEK_MODEL:-deepseek-chat} DASHSCOPE_API_KEY: ${DASHSCOPE_API_KEY:-} QWEN_MODEL: ${QWEN_MODEL:-qwen-plus} LOG_LEVEL: ${LOG_LEVEL:-INFO} APP_ENV: ${APP_ENV:-development} volumes: - ./data:/app/data - ./logs:/app/logs ports: - "8000:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy milvus: condition: service_healthy embedding-service: condition: service_healthy networks: [compliance-net] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 5 start_period: 30s celery-worker: build: context: ./services/compliance-backend dockerfile: Dockerfile image: compliance-backend:latest container_name: compliance-worker restart: unless-stopped command: > celery -A app.worker worker --loglevel=info --concurrency=4 --queues=default,parse,vectorize,compliance,monitor,push env_file: .env environment: DATABASE_URL: postgresql+asyncpg://compliance:${POSTGRES_PASSWORD:-compliance123}@postgres:5432/compliance_db REDIS_URL: redis://:${REDIS_PASSWORD:-redis123}@redis:6379/0 MILVUS_HOST: milvus MILVUS_PORT: "19530" NEO4J_URI: bolt://neo4j:7687 NEO4J_USER: neo4j NEO4J_PASSWORD: ${NEO4J_PASSWORD:-neo4j123} EMBEDDING_SERVICE_URL: http://embedding-service:8010 MCP_SERVER_URL: http://mcp-server:8011 LLM_PROVIDER: ${LLM_PROVIDER:-deepseek} DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} DASHSCOPE_API_KEY: ${DASHSCOPE_API_KEY:-} volumes: - ./data:/app/data - ./logs:/app/logs depends_on: redis: condition: service_healthy compliance-backend: condition: service_healthy networks: [compliance-net] celery-beat: build: context: ./services/compliance-backend dockerfile: Dockerfile image: compliance-backend:latest container_name: compliance-beat restart: unless-stopped command: > celery -A app.worker beat --loglevel=info --scheduler celery.beat.PersistentScheduler env_file: .env environment: DATABASE_URL: postgresql+asyncpg://compliance:${POSTGRES_PASSWORD:-compliance123}@postgres:5432/compliance_db REDIS_URL: redis://:${REDIS_PASSWORD:-redis123}@redis:6379/0 DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-} volumes: - ./data:/app/data - ./logs:/app/logs depends_on: redis: condition: service_healthy networks: [compliance-net] # ═══════════════════════════════════════════════ # API 网关 # ═══════════════════════════════════════════════ nginx: image: nginx:1.25-alpine container_name: compliance-nginx restart: unless-stopped volumes: - ./config/nginx.conf:/etc/nginx/conf.d/default.conf:ro ports: - "80:80" depends_on: compliance-backend: condition: service_healthy networks: [compliance-net] healthcheck: test: ["CMD", "nginx", "-t"] interval: 30s # ═══════════════════════════════════════════════ # 监控(可选,--profile monitoring 启动) # ═══════════════════════════════════════════════ grafana: image: grafana/grafana:11.0.0 container_name: compliance-grafana restart: unless-stopped environment: GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_USERS_ALLOW_SIGN_UP: "false" volumes: - ./config/prometheus.yml:/etc/grafana/provisioning/datasources/prometheus.yml:ro ports: - "3000:3000" networks: [compliance-net] profiles: [monitoring] prometheus: image: prom/prometheus:v2.51.0 container_name: compliance-prometheus restart: unless-stopped volumes: - ./config/prometheus.yml:/etc/prometheus/prometheus.yml:ro ports: - "9090:9090" networks: [compliance-net] profiles: [monitoring]