# docker-compose.yml (生产环境) version: '3.8' services: # ========== 搜索引擎 ========== searxng: container_name: cyrene_searxng image: searxng/searxng:latest volumes: - ./searxng/settings.yml:/etc/searxng/settings.yml:ro environment: SEARXNG_SETTINGS_PATH: /etc/searxng/settings.yml restart: unless-stopped # ========== 反向代理 ========== caddy: container_name: cyrene_caddy image: caddy:2-alpine ports: - "${CADDY_HTTP_PORT:-80}:80" - "${CADDY_HTTPS_PORT:-443}:443" environment: DOMAIN: ${DOMAIN:-} ACME_EMAIL: ${ACME_EMAIL:-admin@localhost} volumes: - ./Caddyfile:/etc/caddy/Caddyfile - caddy_data:/data depends_on: - gateway restart: unless-stopped # ========== 后端服务 ========== gateway: container_name: cyrene_gateway build: context: . dockerfile: ./backend/gateway/Dockerfile environment: ENV: production GATEWAY_PORT: "8080" JWT_SECRET: ${JWT_SECRET} JWT_EXPIRY_HOURS: ${JWT_EXPIRY_HOURS:-720} INTERNAL_SERVICE_TOKEN: ${INTERNAL_SERVICE_TOKEN} ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} ADMIN_PASSWORD: ${ADMIN_PASSWORD} ADMIN_NICKNAME: ${ADMIN_NICKNAME:-管理员} REGISTRATION_ENABLED: ${REGISTRATION_ENABLED:-false} ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-http://localhost:5173,http://localhost:9090} WS_MAX_CONNECTIONS: ${WS_MAX_CONNECTIONS:-1000} SESSION_IDLE_TIMEOUT_MIN: ${SESSION_IDLE_TIMEOUT_MIN:-30} WEBHOOK_API_KEY: ${WEBHOOK_API_KEY:-} LLM_API_URL: ${LLM_API_URL} LLM_API_KEY: ${LLM_API_KEY} LLM_MODEL: ${LLM_MODEL:-gpt-4o} AI_CORE_URL: http://ai-core:8081 MEMORY_SERVICE_URL: http://memory-service:8091 VOICE_SERVICE_URL: http://voice-service:8093 IOT_DEBUG_SERVICE_URL: http://iot-debug-service:8083 POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_USER: ${POSTGRES_USER:-cyrene} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-cyrene_ai} REDIS_HOST: redis REDIS_PORT: "6379" REDIS_PASSWORD: ${REDIS_PASSWORD:-} depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped ai-core: container_name: cyrene_ai_core build: context: . dockerfile: ./backend/ai-core/Dockerfile environment: AI_CORE_PORT: "8081" PERSONA_DIR: "./internal/persona" ENV: production LLM_API_URL: ${LLM_API_URL} LLM_API_KEY: ${LLM_API_KEY} LLM_MODEL: ${LLM_MODEL:-gpt-4o} LLM_FALLBACK_MODEL: ${LLM_FALLBACK_MODEL:-gpt-4o-mini} INTERNAL_SERVICE_TOKEN: ${INTERNAL_SERVICE_TOKEN} ADMIN_NICKNAME: ${ADMIN_NICKNAME:-管理员} GATEWAY_URL: http://gateway:8080 MEMORY_SERVICE_URL: http://memory-service:8091 IOT_DEBUG_SERVICE_URL: http://iot-debug-service:8083 SEARXNG_URL: http://searxng:8080 ENABLE_BACKGROUND_THINKING: ${ENABLE_BACKGROUND_THINKING:-true} ENABLE_TOOLS: "true" TZ: Asia/Shanghai POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_USER: ${POSTGRES_USER:-cyrene} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-cyrene_ai} POSTGRES_SSLMODE: disable depends_on: postgres: condition: service_healthy restart: unless-stopped memory-service: container_name: cyrene_memory_service build: context: . dockerfile: ./backend/memory-service/Dockerfile environment: PORT: "8091" POSTGRES_HOST: postgres POSTGRES_PORT: "5432" POSTGRES_USER: ${POSTGRES_USER:-cyrene} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-cyrene_ai} POSTGRES_SSLMODE: disable depends_on: postgres: condition: service_healthy restart: unless-stopped voice-service: container_name: cyrene_voice_service build: context: . dockerfile: ./backend/voice-service/Dockerfile environment: PORT: "8093" WHISPER_BINARY: "./whisper.cpp/main" WHISPER_MODEL: "./whisper.cpp/models/ggml-small.bin" WHISPER_LANGUAGE: "zh" restart: unless-stopped iot-debug-service: container_name: cyrene_iot_debug_service build: context: . dockerfile: ./backend/iot-debug-service/Dockerfile environment: IOT_DEBUG_PORT: "8083" restart: unless-stopped # ========== 管理控制台 ========== ethend: container_name: cyrene_ethend build: context: ./ethend dockerfile: Dockerfile environment: ETHEND_PORT: "${ETHEND_PORT:-9090}" GATEWAY_URL: http://gateway:8080 AI_CORE_URL: http://ai-core:8081 MEMORY_SERVICE_URL: http://memory-service:8091 VOICE_SERVICE_URL: http://voice-service:8093 IOT_DEBUG_SERVICE_URL: http://iot-debug-service:8083 ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} ADMIN_PASSWORD: ${ADMIN_PASSWORD} ports: - "${ETHEND_PORT:-9090}:9090" depends_on: - gateway restart: unless-stopped # ========== 基础设施 ========== postgres: container_name: cyrene_postgres image: pgvector/pgvector:pg16 volumes: - pg_data:/var/lib/postgresql/data environment: POSTGRES_USER: ${POSTGRES_USER:-cyrene} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-cyrene_ai} healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-cyrene} -d ${POSTGRES_DB:-cyrene_ai}"] interval: 10s timeout: 3s retries: 5 restart: unless-stopped redis: container_name: cyrene_redis image: redis:7-alpine volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 5 restart: unless-stopped qdrant: container_name: cyrene_qdrant image: qdrant/qdrant:latest volumes: - qdrant_data:/qdrant/storage restart: unless-stopped minio: container_name: cyrene_minio image: minio/minio:latest command: server /data environment: MINIO_ROOT_USER: ${MINIO_ACCESS_KEY} MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY} volumes: - minio_data:/data restart: unless-stopped volumes: caddy_data: pg_data: redis_data: qdrant_data: minio_data: