214 lines
6.7 KiB
YAML
214 lines
6.7 KiB
YAML
# Dashboard Nanobot 离线部署编排文件(Full 模式)
|
||
#
|
||
# 说明:
|
||
# 1. 当前文件用于“前端 + 后端 + PostgreSQL + Redis”整套部署。
|
||
# 2. 客户通常只需要修改:
|
||
# - .env 里的 NGINX_PORT、HOST_BOTS_WORKSPACE_ROOT、数据库密码
|
||
# - volumes 里的宿主机挂载路径(如果不想用默认值)
|
||
# 3. HOST_BOTS_WORKSPACE_ROOT 必须是宿主机绝对路径。
|
||
# 4. /var/run/docker.sock 必须保留挂载,否则后端无法管理 Bot 容器。
|
||
|
||
services:
|
||
# PostgreSQL 数据库服务
|
||
postgres:
|
||
image: ${POSTGRES_IMAGE:-postgres:16-alpine}
|
||
container_name: dashboard-nanobot-postgres
|
||
restart: unless-stopped
|
||
|
||
environment:
|
||
TZ: ${TZ:-Asia/Shanghai}
|
||
POSTGRES_USER: ${POSTGRES_SUPERUSER:-postgres}
|
||
POSTGRES_PASSWORD: ${POSTGRES_SUPERPASSWORD:?POSTGRES_SUPERPASSWORD is required}
|
||
POSTGRES_DB: ${POSTGRES_BOOTSTRAP_DB:-postgres}
|
||
|
||
# 数据库存储目录:客户如需改磁盘路径,可直接改左侧宿主机路径
|
||
volumes:
|
||
- ./data/postgres:/var/lib/postgresql/data
|
||
|
||
expose:
|
||
- "5432"
|
||
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 10
|
||
start_period: 20s
|
||
|
||
logging:
|
||
driver: json-file
|
||
options:
|
||
max-size: "20m"
|
||
max-file: "3"
|
||
|
||
# Redis 缓存服务
|
||
redis:
|
||
image: ${REDIS_IMAGE:-redis:7-alpine}
|
||
container_name: dashboard-nanobot-redis
|
||
restart: unless-stopped
|
||
|
||
environment:
|
||
TZ: ${TZ:-Asia/Shanghai}
|
||
|
||
command: ["redis-server", "--appendonly", "yes", "--save", "60", "1000"]
|
||
|
||
# Redis 数据存储目录
|
||
volumes:
|
||
- ./data/redis:/data
|
||
|
||
expose:
|
||
- "6379"
|
||
|
||
healthcheck:
|
||
test: ["CMD", "redis-cli", "ping"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 10
|
||
start_period: 10s
|
||
|
||
logging:
|
||
driver: json-file
|
||
options:
|
||
max-size: "20m"
|
||
max-file: "3"
|
||
|
||
# 后端服务:Dashboard 主 API 服务
|
||
backend:
|
||
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
|
||
|
||
depends_on:
|
||
postgres:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_healthy
|
||
|
||
environment:
|
||
TZ: ${TZ:-Asia/Shanghai}
|
||
APP_HOST: 0.0.0.0
|
||
APP_PORT: 8000
|
||
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_NETWORK_NAME: ${DOCKER_NETWORK_NAME:-dashboard-nanobot-network}
|
||
|
||
# Full 模式下数据库固定连容器内 postgres
|
||
DATABASE_URL: postgresql+psycopg://${POSTGRES_APP_USER}:${POSTGRES_APP_PASSWORD}@postgres:5432/${POSTGRES_APP_DB}
|
||
|
||
# Full 模式下 Redis 固定连容器内 redis
|
||
REDIS_ENABLED: ${REDIS_ENABLED:-true}
|
||
REDIS_URL: redis://redis:6379/${REDIS_DB:-8}
|
||
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}
|
||
|
||
expose:
|
||
- "8000"
|
||
|
||
healthcheck:
|
||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/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:
|
||
TZ: ${TZ:-Asia/Shanghai}
|
||
# 上传大小限制:只限制 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}
|