# sundynix-agentix · 生产/独立部署编排(应用 + 基建一把拉起) # # cp .env.example .env # 然后按提示填密钥(见 DEPLOY.md) # docker compose -f docker-compose.prod.yml up -d --build # # 设计: # - 应用经服务名互连(postgres:5432 等),不依赖 127.0.0.1;基建端口不对宿主暴露(仅内网)。 # - 仅暴露 gateway(:${GATEWAY_PORT},内嵌 admin 控制台 + API + 供桌面端直连) + Jaeger UI(可选)。 # - 引导密钥从 .env 注入(SUNDYNIX_SECRET_KEY/JWT_SECRET/各库密码);模型 API key 仍在控制台配、加密存 PG。 # - APP_ENV=production → 强制校验密钥、锁 CORS、启用管理员白名单。 x-secret-key: &secret-key ${SUNDYNIX_SECRET_KEY:?需在 .env 设置(openssl rand -base64 32)} services: # ---------- 应用层 ---------- gateway: build: { context: ., dockerfile: sundynix-gateway/Dockerfile } image: sundynix/gateway:${TAG:-latest} restart: unless-stopped environment: APP_ENV: production GATEWAY_ADDR: ":8080" NATS_URL: nats://nats:4222 POSTGRES_DSN: postgres://sundynix:${POSTGRES_PASSWORD:?}@postgres:5432/sundynix?sslmode=disable REDIS_ADDR: redis:6379 MINIO_ENDPOINT: minio:9000 MINIO_ACCESS_KEY: minioadmin # minio 仅 compose 内网可达,不对宿主暴露 MINIO_SECRET_KEY: minioadmin SUNDYNIX_SECRET_KEY: *secret-key JWT_SECRET: ${JWT_SECRET:?需在 .env 设置(openssl rand -base64 32)} ADMIN_USER_IDS: ${ADMIN_USER_IDS:-} CORS_ALLOW_ORIGIN: ${CORS_ALLOW_ORIGIN:-*} OTEL_EXPORTER_OTLP_ENDPOINT: http://jaeger:4318 ports: ["${GATEWAY_PORT:-8080}:8080"] depends_on: postgres: { condition: service_healthy } redis: { condition: service_started } nats: { condition: service_started } dispatcher: build: { context: ., dockerfile: sundynix-dispatcher/Dockerfile } image: sundynix/dispatcher:${TAG:-latest} restart: unless-stopped environment: APP_ENV: production NATS_URL: nats://nats:4222 SUNDYNIX_SECRET_KEY: *secret-key OTEL_EXPORTER_OTLP_ENDPOINT: http://jaeger:4318 DISPATCHER_CONCURRENCY: ${DISPATCHER_CONCURRENCY:-8} TASK_TOKEN_BUDGET: ${TASK_TOKEN_BUDGET:-200000} depends_on: nats: { condition: service_started } mcp-go: build: { context: ., dockerfile: sundynix-mcp-go/Dockerfile } image: sundynix/mcp-go:${TAG:-latest} restart: unless-stopped environment: APP_ENV: production NATS_URL: nats://nats:4222 POSTGRES_DSN: postgres://sundynix:${POSTGRES_PASSWORD:?}@postgres:5432/sundynix?sslmode=disable REDIS_ADDR: redis:6379 MILVUS_ADDR: milvus:19530 NEO4J_URI: neo4j://neo4j:7687 NEO4J_USER: neo4j NEO4J_PASS: ${NEO4J_PASSWORD:?} # 报告源/产物 + KB 正文对象存储(blob)——与 gateway 同一 MinIO,勿漏否则 fallback localhost。 MINIO_ENDPOINT: minio:9000 MINIO_ACCESS_KEY: minioadmin MINIO_SECRET_KEY: minioadmin MINIO_BUCKET: sundynix-docs SUNDYNIX_SECRET_KEY: *secret-key OTEL_EXPORTER_OTLP_ENDPOINT: http://jaeger:4318 # 全文(bleve)索引落盘位置。不设则相对 CWD,写进容器可写层 → 每次重建容器就清零, # 而混合检索只是静默少一路召回、不报错,很难发现。必须配合下面的持久卷。 BLEVE_PATH: /data/bleve depends_on: nats: { condition: service_started } milvus: { condition: service_healthy } # mcp-go 须在 Milvus 后起,否则工具 no responders volumes: - mcp_go_data:/data mcp-py: build: { context: sundynix-mcp-py, dockerfile: Dockerfile } image: sundynix/mcp-py:${TAG:-latest} restart: unless-stopped environment: NATS_URL: nats://nats:4222 # secure_sandbox(代码隔离执行)需访问宿主 Docker 拉起一次性容器。 # 安全敏感:等于把宿主 Docker 暴露给该服务;不需要代码执行工具可注释掉这行。 volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: nats: { condition: service_started } # admin 运维控制台已内嵌进 gateway(go:embed,见 sundynix-gateway/internal/webui), # 不再需要单独的 nginx 容器:访问 gateway:${GATEWAY_PORT} 即同时得到控制台 UI + API。 # ---------- 基础设施(端口不对宿主暴露,仅 compose 内网) ---------- nats: image: nats:2-alpine command: ["-c", "/etc/nats/nats-server.conf"] restart: unless-stopped volumes: - ./deploy/nats/nats-server.conf:/etc/nats/nats-server.conf:ro - nats_data:/data/jetstream postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: sundynix POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?} POSTGRES_DB: sundynix volumes: ["pg_data:/var/lib/postgresql/data"] healthcheck: test: ["CMD-SHELL", "pg_isready -U sundynix"] interval: 5s timeout: 5s retries: 10 redis: image: redis:7-alpine restart: unless-stopped volumes: ["redis_data:/data"] jaeger: image: jaegertracing/all-in-one:1.60 restart: unless-stopped environment: COLLECTOR_OTLP_ENABLED: "true" ports: ["${JAEGER_UI_PORT:-16686}:16686"] # 链路追踪 UI(演示可看 span 瀑布图;不需要可去掉) milvus-etcd: image: quay.io/coreos/etcd:v3.5.14 restart: unless-stopped environment: ETCD_AUTO_COMPACTION_MODE: revision ETCD_AUTO_COMPACTION_RETENTION: "1000" ETCD_QUOTA_BACKEND_BYTES: "4294967296" ETCD_SNAPSHOT_COUNT: "50000" command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd volumes: ["milvus_etcd:/etcd"] minio: image: minio/minio:RELEASE.2023-03-20T20-16-18Z restart: unless-stopped environment: MINIO_ACCESS_KEY: minioadmin # 内网专用(不对宿主暴露端口),与 milvus/gateway 默认对齐 MINIO_SECRET_KEY: minioadmin command: minio server /minio_data volumes: ["minio_data:/minio_data"] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 milvus: image: milvusdb/milvus:v2.4.13 command: ["milvus", "run", "standalone"] restart: unless-stopped environment: ETCD_ENDPOINTS: milvus-etcd:2379 MINIO_ADDRESS: minio:9000 volumes: ["milvus_data:/var/lib/milvus"] healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"] interval: 15s timeout: 10s retries: 10 depends_on: [milvus-etcd, minio] neo4j: image: neo4j:5-community restart: unless-stopped environment: NEO4J_AUTH: neo4j/${NEO4J_PASSWORD:?} volumes: ["neo4j_data:/data"] volumes: nats_data: pg_data: redis_data: milvus_etcd: minio_data: milvus_data: neo4j_data: mcp_go_data: