Files
sundynix-agentix/docker-compose.prod.yml
T
Blizzard c1420b5665 fix(rag): 全文索引在容器里根本没持久化 —— 补 /data 卷 + BLEVE_PATH
排查「fulltext 路 0 命中」时发现的真问题,比原以为的分词器问题严重得多。

现状:mcp-go 容器**没有任何 volume**,也没设 BLEVE_PATH,于是索引落到相对
CWD 的 .data/bleve。而运行阶段没有 WORKDIR(CWD=/)、进程又是非 root(uid 10001),
两种结局都糟:
  - 在 / 下建不了目录 → openBleve 静默退回内存索引,重启即清零;
  - 就算建得了,也只是写进容器可写层,每次发版重建容器一样清零。
更糟的是它不报错:混合检索少一路只表现为召回变差,看不出故障。

改动:
  - Dockerfile:建 /data 并 chown 给 app,WORKDIR 设为 /data;
  - 两份 compose:BLEVE_PATH=/data/bleve + 挂持久卷(132 那份此前连
    顶层 volumes 段都没有);
  - .env.example:写清默认相对路径相对的是**启动目录**——本地从仓库根起
    和从 sundynix-mcp-go/ 起会写出两份互不相干的索引,排查时极易被坑。

附带澄清:中文分词本身没问题。直接开落盘索引验证过,mapping 里 text 字段
确实是 cjk,实测「星间链」命中 4 条、「海关监管」命中 104 条,BM25 打分正常。
a4852c3 那次修复是有效的,之前怀疑分词器的判断作废。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 13:40:31 +08:00

190 lines
6.9 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 运维控制台已内嵌进 gatewaygo: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: