282 lines
12 KiB
YAML
282 lines
12 KiB
YAML
# ==============================
|
||
# 魂镜应用层编排(后端 FastAPI + 前端 Next.js)。
|
||
# 与基础设施 docker-compose.infra.yml 解耦:本文件以 external 方式引用共享网络 hunjing-net,
|
||
# 通过服务名(hunjing-postgres / hunjing-redis / hunjing-milvus / hunjing-neo4j / hunjing-nebula-graphd)连接基础设施。
|
||
#
|
||
# 前置:先启动基础设施以创建 hunjing-net 网络与所需数据库等:
|
||
# docker compose -f docker/docker-compose.infra.yml up -d
|
||
#
|
||
# 常用命令:
|
||
# # 启动前后端(会构建镜像)
|
||
# docker compose -f docker/docker-compose.app.yml up -d --build
|
||
# # 仅启动后端 / 前端
|
||
# docker compose -f docker/docker-compose.app.yml up -d hunjing-backend
|
||
# docker compose -f docker/docker-compose.app.yml up -d hunjing-frontend
|
||
# # 查看日志
|
||
# docker compose -f docker/docker-compose.app.yml logs -f hunjing-backend
|
||
# # 停止
|
||
# docker compose -f docker/docker-compose.app.yml down
|
||
#
|
||
# 内存限制:每个服务通过 deploy.resources.limits/reservations 约束内存,可按宿主机规格调整。
|
||
# ==============================
|
||
name: hunjing
|
||
|
||
networks:
|
||
hunjing-net:
|
||
external: true
|
||
name: hunjing-net
|
||
# 沙箱专属内部网络:internal=true 禁止公网出站,仅同网络容器互访。
|
||
# 后端通过此网络访问沙箱;沙箱不接入 hunjing-net,彻底切断其公网出口,防数据外泄。
|
||
sandbox-net:
|
||
internal: true
|
||
name: hunjing-sandbox-net
|
||
|
||
services:
|
||
# ============================== 灵台 · 后端 FastAPI(Backend) ==============================
|
||
hunjing-backend:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/backend/Dockerfile
|
||
image: hunjing-backend:latest
|
||
container_name: hunjing-backend
|
||
restart: unless-stopped
|
||
networks: [hunjing-net, sandbox-net]
|
||
# 注入根目录 .env(含模型密钥等);缺失时启动会报错,请先 `cp .env.example .env`。
|
||
env_file:
|
||
- ../.env
|
||
environment:
|
||
# 覆盖容器网络服务发现地址(优先级高于 env_file),保持 .env 中 127.0.0.1 默认值不变。
|
||
APP_ENV: production
|
||
DATABASE_TYPE: pgsql
|
||
POSTGRES_HOST: hunjing-postgres
|
||
POSTGRES_PORT: "5432"
|
||
REDIS_HOST: hunjing-redis
|
||
MILVUS_HOST: hunjing-milvus
|
||
NEO4J_URI: bolt://hunjing-neo4j:7687
|
||
NEBULAGRAPH_HOST: hunjing-nebula-graphd
|
||
MINIO_ENDPOINT: http://hunjing-minio:9000
|
||
STORAGE_PROVIDER: ${STORAGE_PROVIDER:-local}
|
||
# rewrite/1.0:模型出口走神识网关(覆盖 .env 默认空值;令牌经 env_file 注入)
|
||
SHENSHI_BASE_URL: http://hunjing-shenshi:8080
|
||
volumes:
|
||
# bind mount 到 /app 下的对应目录,使 .env 相对路径 ../logs ../db ../storage ../config 生效。
|
||
- ../logs:/app/logs
|
||
- ../db:/app/db
|
||
- ../storage:/app/storage
|
||
- ../config:/app/config:ro
|
||
ports:
|
||
- "${BACKEND_PORT:-8000}:8000"
|
||
# 注意:数据库等基础设施位于 infra 文件,跨文件无法用 depends_on 表达。
|
||
# 请先启动 infra;后端自身应有数据库连接重试逻辑以应对基础设施尚未就绪的情况。
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 1G }
|
||
reservations: { memory: 256M }
|
||
|
||
# ============================== 神识 · 模型网关(Go,rewrite/1.0 M0) ==============================
|
||
# 灵台唯一模型出口:IR 入站 → 适配器(当前 stub,云 Provider/元炁按 M4 接入)→ SSE 出站。
|
||
# 鉴权:SHENSHI_SERVICE_TOKEN 经 env_file 注入;未配置时开发档放行。
|
||
hunjing-shenshi:
|
||
build:
|
||
context: ../shenshi
|
||
dockerfile: ../docker/shenshi/Dockerfile
|
||
image: hunjing-shenshi:latest
|
||
container_name: hunjing-shenshi
|
||
restart: unless-stopped
|
||
networks: [hunjing-net]
|
||
env_file:
|
||
- ../.env
|
||
environment:
|
||
SHENSHI_PORT: "8080"
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 256M }
|
||
reservations: { memory: 64M }
|
||
|
||
# ============================== 照壁 · BFF(Fastify,rewrite/1.0 M0) ==============================
|
||
# 客户端与灵台之间的无状态通道:鉴权透传、SSE 直通、响应透传。无业务规则、无权威数据。
|
||
hunjing-bff:
|
||
build:
|
||
context: ../bff
|
||
dockerfile: ../docker/bff/Dockerfile
|
||
image: hunjing-bff:latest
|
||
container_name: hunjing-bff
|
||
restart: unless-stopped
|
||
networks: [hunjing-net]
|
||
environment:
|
||
BFF_PORT: "3000"
|
||
BACKEND_URL: http://hunjing-backend:8000
|
||
depends_on:
|
||
hunjing-backend:
|
||
condition: service_started
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 256M }
|
||
reservations: { memory: 64M }
|
||
|
||
# ============================== 琉璃镜 · 前端 Next.js(Frontend) ==============================
|
||
hunjing-frontend:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/frontend/Dockerfile
|
||
image: hunjing-frontend:latest
|
||
container_name: hunjing-frontend
|
||
restart: unless-stopped
|
||
networks: [hunjing-net]
|
||
environment:
|
||
NODE_ENV: production
|
||
# 容器内 Next 服务端(BFF)通过容器网络服务名连后端;浏览器只同源访问前端,
|
||
# 所有请求经 BFF(/api/proxy、/api/sse、/api/auth),不需要后端地址。
|
||
BACKEND_URL: http://hunjing-backend:8000
|
||
ports:
|
||
- "${FRONTEND_PORT:-3000}:3000"
|
||
depends_on:
|
||
hunjing-backend:
|
||
condition: service_started
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 512M }
|
||
reservations: { memory: 128M }
|
||
|
||
# ============================== 乾坤 · 安全沙箱(可选,profile: sandbox,Rust 微服务 / Sandbox Engine) ==============================
|
||
# 为百工 Tool Runtime 提供本地隔离的命令执行层(POST /v1/exec,GET /healthz)。详见 sandbox/README.md。
|
||
# 启用:docker compose -f docker/docker-compose.app.yml --profile sandbox up -d --build hunjing-sandbox
|
||
#
|
||
# 容器级隔离加固(沙箱进程内另有进程组 / 超时 / 输出截断 / 路径逃逸拒绝,见 sandbox/README.md):
|
||
# - 网络:仅接入 internal 的 sandbox-net,无公网出站;后端通过该网络以服务名 hunjing-sandbox 访问。
|
||
# - 资源:pids_limit 防 fork bomb、cpus+memory 限额防 CPU/内存耗尽、/tmp 走 tmpfs 限大小防磁盘写满。
|
||
# - 权限:read-only 根、no-new-privileges、cap_drop ALL、默认 seccomp profile(最小权限)。
|
||
# - 更强隔离(自定义 seccomp 白名单 / nsjail·gVisor·microVM)见 sandbox/README.md「后续加固」。
|
||
hunjing-sandbox:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/sandbox/Dockerfile
|
||
image: hunjing-sandbox:latest
|
||
container_name: hunjing-sandbox
|
||
profiles: ["sandbox"]
|
||
restart: unless-stopped
|
||
networks: [sandbox-net]
|
||
# 注入根目录 .env(与 backend 一致)。compose 的 ${} 插值不查找项目根 .env(插值源是
|
||
# compose 文件所在目录 docker/.env,不存在),故 SANDBOX_AUTH_SECRET 必须经 env_file 注入
|
||
# 容器;environment 块不重设它以免覆盖。executor 另有 env_clear + allowed_env 白名单
|
||
# (仅 PATH/HOME/TZ/LANG),被执行的子进程拿不到本环境里的其他敏感变量。
|
||
env_file:
|
||
- ../.env
|
||
environment:
|
||
SANDBOX_HOST: 0.0.0.0
|
||
SANDBOX_PORT: "8090"
|
||
SANDBOX_BASE_WORKDIR: /app/sandbox-work
|
||
SANDBOX_LOG_DIR: /app/logs
|
||
SANDBOX_MAX_TIMEOUT_MS: ${SANDBOX_MAX_TIMEOUT_MS:-30000}
|
||
SANDBOX_MAX_CONCURRENT: ${SANDBOX_MAX_CONCURRENT:-8}
|
||
SANDBOX_MAX_OUTPUT_BYTES: ${SANDBOX_MAX_OUTPUT_BYTES:-1048576}
|
||
SANDBOX_ALLOWED_ENV: ${SANDBOX_ALLOWED_ENV:-PATH,HOME,TZ,LANG}
|
||
SANDBOX_AUTH_ENABLED: ${SANDBOX_AUTH_ENABLED:-true}
|
||
RUST_LOG: ${RUST_LOG:-info}
|
||
volumes:
|
||
# 持久化沙箱工作目录到项目根 sandbox-work/(已加入 .gitignore)
|
||
- ../sandbox-work:/app/sandbox-work
|
||
# 日志写到项目根 logs/sandbox.log(与后端 app.log 同目录,便于统一查看/收集)
|
||
- ../logs:/app/logs
|
||
# /tmp 走 tmpfs(64M),限制临时文件占用,防止写满磁盘
|
||
tmpfs:
|
||
- /tmp:size=67108864,mode=1777
|
||
# 最小权限加固:只读根文件系统(仅 /tmp tmpfs 与 sandbox-work bind mount 可写)、
|
||
# 禁止子进程提权(no-new-privileges)、丢弃所有 capabilities(kill 进程组属同 UID 操作无需 cap)。
|
||
# seccomp 用 Docker 默认 profile。
|
||
read_only: true
|
||
security_opt:
|
||
- no-new-privileges:true
|
||
cap_drop:
|
||
- ALL
|
||
ports:
|
||
- "${SANDBOX_PORT:-8090}:8090"
|
||
# 进程数与 CPU 限额:防 fork bomb 与 CPU 耗尽(pids/cpus 随 deploy.resources 在非 swarm 下生效)
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 512M, cpus: "1.0", pids: 256 }
|
||
reservations: { memory: 64M }
|
||
|
||
# ============================== 元炁 · 本地推理引擎(可选,profile: yuanqi,Local Inference Engine) ==============================
|
||
# 纯 Python 本地推理引擎,提供 LLM / Embedding / Reranker / 多模态推理能力。
|
||
# 所有模型文件存放在项目根目录 models/ 下,容器启动时挂载到 /app/models。
|
||
# 启用:docker compose -f docker/docker-compose.app.yml --profile yuanqi up -d --build hunjing-yuanqi
|
||
hunjing-yuanqi:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/yuanqi/Dockerfile
|
||
image: hunjing-yuanqi:latest
|
||
container_name: hunjing-yuanqi
|
||
profiles: ['yuanqi']
|
||
restart: unless-stopped
|
||
networks: [hunjing-net]
|
||
environment:
|
||
YUANQI_HOST: 0.0.0.0
|
||
YUANQI_PORT: '11434'
|
||
YUANQI_MODELS_DIR: /app/models
|
||
YUANQI_DEVICE: ${YUANQI_DEVICE:-auto}
|
||
YUANQI_LOG_LEVEL: ${YUANQI_LOG_LEVEL:-info}
|
||
volumes:
|
||
- ../models:/app/models:ro
|
||
- ../logs:/app/logs
|
||
ports:
|
||
- '${YUANQI_PORT:-11434}:11434'
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 4G }
|
||
reservations: { memory: 1G }
|
||
|
||
# ============================== 天目 · 本地 OCR 引擎(可选,profile: tianmu) ==============================
|
||
# 本地 OCR 推理引擎,提供 PP-OCRv6 快速文字提取 + PaddleOCR-VL-1.6 复杂文档解析。
|
||
# 所有模型文件存放在项目根目录 models/ 下,容器启动时挂载到 /app/models。
|
||
# 启用:docker compose -f docker/docker-compose.app.yml --profile tianmu up -d --build hunjing-tianmu
|
||
hunjing-tianmu:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/tianmu/Dockerfile
|
||
image: hunjing-tianmu:latest
|
||
container_name: hunjing-tianmu
|
||
profiles: ['tianmu']
|
||
restart: unless-stopped
|
||
networks: [hunjing-net]
|
||
environment:
|
||
TIANMU_HOST: '0.0.0.0'
|
||
TIANMU_PORT: '8101'
|
||
TIANMU_MODELS_DIR: /app/models
|
||
TIANMU_DEVICE: ${TIANMU_DEVICE:-auto}
|
||
TIANMU_LOG_LEVEL: ${TIANMU_LOG_LEVEL:-info}
|
||
volumes:
|
||
- ../models:/app/models:ro
|
||
- ../logs:/app/logs
|
||
ports:
|
||
- '${TIANMU_PORT:-8101}:8101'
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 4G }
|
||
reservations: { memory: 1G }
|
||
|
||
# ============================== 天门 · 反向代理(Nginx,可选,profile: nginx,统一入口) ==============================
|
||
# 对外只暴露 80:/api/* 与 SSE 走后端,其余走前端。配置见 docker/nginx/nginx.conf。
|
||
# 启用:docker compose -f docker/docker-compose.app.yml --profile nginx up -d hunjing-nginx
|
||
hunjing-nginx:
|
||
image: nginx:1.27-alpine
|
||
container_name: hunjing-nginx
|
||
profiles: ["nginx"]
|
||
restart: unless-stopped
|
||
networks: [hunjing-net]
|
||
volumes:
|
||
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||
ports:
|
||
- "${NGINX_PORT:-80}:80"
|
||
depends_on:
|
||
hunjing-backend:
|
||
condition: service_started
|
||
hunjing-bff:
|
||
condition: service_started
|
||
hunjing-frontend:
|
||
condition: service_started
|
||
deploy:
|
||
resources:
|
||
limits: { memory: 128M }
|
||
reservations: { memory: 32M }
|