dashboard-nanobot/offline/docker-compose.prod.yml

150 lines
5.5 KiB
YAML
Raw Normal View History

# Dashboard Nanobot 离线部署编排文件Prod 模式)
#
# 说明:
# 1. 当前文件用于“前端 + 后端”部署,数据库和 Redis 由客户外部提供。
# 2. 客户通常只需要修改:
# - .env 里的 NGINX_PORT、DATABASE_URL、REDIS_URL、HOST_BOTS_WORKSPACE_ROOT
# - volumes 里的宿主机挂载路径(如果不想用默认值)
# 3. HOST_BOTS_WORKSPACE_ROOT 必须是宿主机绝对路径。
# 4. /var/run/docker.sock 必须保留挂载,否则后端无法管理 Bot 容器。
services:
# 后端服务Dashboard 主 API 服务
backend:
# 镜像构建配置:正常情况下客户离线部署不需要重新 build
# 但保留 build 信息方便后续有源码时重新构建。
build:
context: .
dockerfile: backend/Dockerfile
args:
PYTHON_BASE_IMAGE: ${PYTHON_BASE_IMAGE:-python:3.12-slim}
PIP_INDEX_URL: ${PIP_INDEX_URL:-https://pypi.org/simple}
PIP_TRUSTED_HOST: ${PIP_TRUSTED_HOST:-}
# 后端镜像名:由离线导入的镜像提供
image: dashboard-nanobot/backend:${BACKEND_IMAGE_TAG:-latest}
container_name: dashboard-nanobot-backend
restart: unless-stopped
# 运行环境变量数据库、Redis、语音识别等主要配置都走这里
environment:
APP_HOST: 0.0.0.0
APP_PORT: 8002
APP_RELOAD: "false"
DATABASE_ECHO: "false"
DATABASE_POOL_SIZE: ${DATABASE_POOL_SIZE:-20}
DATABASE_MAX_OVERFLOW: ${DATABASE_MAX_OVERFLOW:-40}
DATABASE_POOL_TIMEOUT: ${DATABASE_POOL_TIMEOUT:-30}
DATABASE_POOL_RECYCLE: ${DATABASE_POOL_RECYCLE:-1800}
DATA_ROOT: /app/data
# Bot 工作目录:必须和宿主机路径保持一致
BOTS_WORKSPACE_ROOT: ${HOST_BOTS_WORKSPACE_ROOT}
# Docker 网络名:通常不用改,除非客户现场网络有冲突
DOCKER_NETWORK_NAME: ${DOCKER_NETWORK_NAME:-dashboard-nanobot-network}
# 外部 PostgreSQL 连接串Prod 模式客户必须改这里
DATABASE_URL: ${DATABASE_URL:-}
# 外部 Redis 配置:如果不用 Redis可把 REDIS_ENABLED 改成 false
REDIS_ENABLED: ${REDIS_ENABLED:-false}
REDIS_URL: ${REDIS_URL:-}
REDIS_PREFIX: ${REDIS_PREFIX:-dashboard_nanobot}
REDIS_DEFAULT_TTL: ${REDIS_DEFAULT_TTL:-60}
DEFAULT_BOT_SYSTEM_TIMEZONE: ${DEFAULT_BOT_SYSTEM_TIMEZONE:-Asia/Shanghai}
PANEL_ACCESS_PASSWORD: ${PANEL_ACCESS_PASSWORD:-}
WORKSPACE_PREVIEW_SIGNING_SECRET: ${WORKSPACE_PREVIEW_SIGNING_SECRET:-}
WORKSPACE_PREVIEW_TOKEN_TTL_SECONDS: ${WORKSPACE_PREVIEW_TOKEN_TTL_SECONDS:-3600}
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS:-}
# 语音识别模型配置:如果启用 STT模型文件需要放到 data/model/
STT_ENABLED: ${STT_ENABLED:-true}
STT_MODEL: ${STT_MODEL:-ggml-small-q8_0.bin}
STT_MODEL_DIR: ${STT_MODEL_DIR:-/app/data/model}
STT_DEVICE: ${STT_DEVICE:-cpu}
STT_MAX_AUDIO_SECONDS: ${STT_MAX_AUDIO_SECONDS:-20}
STT_DEFAULT_LANGUAGE: ${STT_DEFAULT_LANGUAGE:-zh}
STT_FORCE_SIMPLIFIED: ${STT_FORCE_SIMPLIFIED:-true}
STT_AUDIO_PREPROCESS: ${STT_AUDIO_PREPROCESS:-true}
STT_AUDIO_FILTER: ${STT_AUDIO_FILTER:-highpass=f=120,lowpass=f=7600,afftdn=nf=-20}
STT_INITIAL_PROMPT: ${STT_INITIAL_PROMPT:-以下内容可能包含简体中文和英文术语。请优先输出简体中文,英文单词、缩写、品牌名和数字保持原文,不要翻译。}
# 关键挂载:
# 1. docker.sock必须保留
# 2. ./data建议保留在交付目录下
# 3. HOST_BOTS_WORKSPACE_ROOT客户可按现场路径修改
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/app/data
- ${HOST_BOTS_WORKSPACE_ROOT}:${HOST_BOTS_WORKSPACE_ROOT}
# 仅在内部网络暴露给 nginx不直接映射到宿主机端口
expose:
- "8002"
# 健康检查:用于确保 nginx 只在后端健康后启动
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8002/api/health', timeout=3).read()"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
# 前端服务Nginx 托管前端并反向代理后端 API
nginx:
build:
context: ./frontend
dockerfile: Dockerfile
args:
NODE_BASE_IMAGE: ${NODE_BASE_IMAGE:-node:22-alpine}
NGINX_BASE_IMAGE: ${NGINX_BASE_IMAGE:-nginx:alpine}
NPM_REGISTRY: ${NPM_REGISTRY:-https://registry.npmjs.org/}
VITE_API_BASE: /api
VITE_WS_BASE: /ws/monitor
image: dashboard-nanobot/nginx:${FRONTEND_IMAGE_TAG:-latest}
container_name: dashboard-nanobot-nginx
restart: unless-stopped
environment:
# 上传大小限制:只限制 Nginx 入口
UPLOAD_MAX_MB: ${UPLOAD_MAX_MB:-100}
depends_on:
backend:
condition: service_healthy
# 对外访问端口:客户通常会改这个
ports:
- "${NGINX_PORT}:80"
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1/"]
interval: 15s
timeout: 5s
retries: 5
start_period: 10s
logging:
driver: json-file
options:
max-size: "20m"
max-file: "3"
# 自定义 Docker 网络:如果客户现场网段冲突,可以改 subnet
networks:
default:
name: ${DOCKER_NETWORK_NAME:-dashboard-nanobot-network}
driver: bridge
ipam:
config:
- subnet: ${DOCKER_NETWORK_SUBNET:-172.20.0.0/16}