Files
wecom_it_smart_desk/docker-compose.yml
T

250 lines
9.3 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.
# =============================================================================
# 企微IT智能服务台 — Docker Compose(公司内网服务器版)
# =============================================================================
# 目标服务器:10.90.5.110
# 域名:itsupport.servyou.com.cn
#
# 用法:
# 1. 上传部署包到服务器
# 2. cp .env.example .env && vim .env # 填入真实配置
# 3. docker compose up -d # 启动所有服务
# 4. docker compose logs -f # 查看日志
#
# 架构:
# 客户端浏览器 → Nginx:80 → { /itdesk/, /itagent/, /itadmin/, /api/, /ws/ }
# =============================================================================
services:
# --------------------------------------------------------------------------
# PostgreSQL 16 — 持久化数据库
# --------------------------------------------------------------------------
postgres:
image: postgres:16-alpine
container_name: wecom_it_postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-wecom}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-wecom_secret}
POSTGRES_DB: ${POSTGRES_DB:-wecom_it_desk}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-wecom}"]
interval: 5s
timeout: 5s
retries: 5
networks:
- it-desk-internal
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# --------------------------------------------------------------------------
# Redis 7 — 缓存服务(token、会话、员工信息)
# --------------------------------------------------------------------------
redis:
image: redis:7-alpine
container_name: wecom_it_redis
restart: unless-stopped
command: redis-server --appendonly yes --save 900 1 --save 300 10 --requirepass "${REDIS_PASSWORD:?REDIS_PASSWORD must be set in .env}"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5
networks:
- it-desk-internal
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# --------------------------------------------------------------------------
# Neo4j 5 — 知识图谱存储(社区版)
# --------------------------------------------------------------------------
neo4j:
image: neo4j:5-community
container_name: wecom_it_neo4j
restart: unless-stopped
environment:
NEO4J_AUTH: neo4j/${NEO4J_PASSWORD}
NEO4J_PLUGINS: '["apoc"]'
volumes:
- neo4j_data:/data
- neo4j_logs:/logs
healthcheck:
test: ["CMD-SHELL", "cypher-shell -u neo4j -p ${NEO4J_PASSWORD} 'RETURN 1'"]
interval: 10s
timeout: 5s
retries: 10
networks:
- it-desk-internal
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# --------------------------------------------------------------------------
# FastAPI 后端 — 核心业务服务
# --------------------------------------------------------------------------
backend:
build:
context: ./backend
dockerfile: Dockerfile
image: wecom-it-desk-backend:latest
container_name: wecom_it_backend
restart: unless-stopped
environment:
# 企微凭证
- WECOM_CORP_ID=${WECOM_CORP_ID}
- WECOM_AGENT_ID=${WECOM_AGENT_ID}
- WECOM_SECRET=${WECOM_SECRET}
- WECOM_APPROVAL_SECRET=${WECOM_APPROVAL_SECRET:-}
- WECOM_TOKEN=${WECOM_TOKEN}
- WECOM_ENCODING_AES_KEY=${WECOM_ENCODING_AES_KEY}
# 企微 SSO 回调地址(扫码登录用)
- WECOM_SSO_CALLBACK_BASE=${WECOM_SSO_CALLBACK_BASE:-https://itsupport.servyou.com.cn}
# ITSM 运维平台(app_id/app_secret 待申请,先占位)
- ITSM_APP_ID=${ITSM_APP_ID:-}
- ITSM_APP_SECRET=${ITSM_APP_SECRET:-}
# 数据库(Docker 内部网络,用容器名通信)
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
# RedisDocker 内部网络)
# v4.0 P1-7:密码改为 .env 注入(原硬编码已入 git 历史,2026-07-18 轮换)
# 新密码为 32 位字母数字,无需 URL 编码;若含特殊字符必须用 REDIS_PASSWORD_ENCODED
- REDIS_URL=redis://:${REDIS_PASSWORD_ENCODED:-${REDIS_PASSWORD}}@redis:6379/0
# 应用环境(v4.0 P1-7 修复:生产 UA 校验和 IP 白名单依赖此变量,此前未传入容器)
- APP_ENV=${APP_ENV:-production}
# CORS
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
# AI 服务(Dify
- DIFY_API_URL=${DIFY_API_URL}
- DIFY_API_KEY=${DIFY_API_KEY}
- DIFY_TIMEOUT=${DIFY_TIMEOUT:-30}
# Dify 原生直连(优先于 dify2openai 代理,修复 [object Object] bug
- DIFY_NATIVE_BASE_URL=${DIFY_NATIVE_BASE_URL:-}
- DIFY_NATIVE_API_KEY=${DIFY_NATIVE_API_KEY:-}
# Dify 双路径超时预算切分(v4.0 P0-612+12 < wait_for 30s
- DIFY_NATIVE_TIMEOUT=${DIFY_NATIVE_TIMEOUT:-12}
- DIFY_PROXY_TIMEOUT=${DIFY_PROXY_TIMEOUT:-12}
# AI Wingman(留空禁用)
- DIFY_WINGMAN_API_URL=${DIFY_WINGMAN_API_URL:-}
- DIFY_WINGMAN_API_KEY=${DIFY_WINGMAN_API_KEY:-}
- DIFY_WINGMAN_TIMEOUT=${DIFY_WINGMAN_TIMEOUT:-30}
# 百度语音识别(ASR
- BAIDU_ASR_APP_ID=${BAIDU_ASR_APP_ID:-}
- BAIDU_ASR_API_KEY=${BAIDU_ASR_API_KEY:-}
- BAIDU_ASR_SECRET_KEY=${BAIDU_ASR_SECRET_KEY:-}
# Neo4j 知识图谱
- NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687}
- NEO4J_USER=${NEO4J_USER:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD}
- NEO4J_DATABASE=${NEO4J_DATABASE:-neo4j}
- NEO4J_MAX_CONNECTION_LIFETIME=${NEO4J_MAX_CONNECTION_LIFETIME:-3600}
- NEO4J_MAX_CONNECTION_POOL_SIZE=${NEO4J_MAX_CONNECTION_POOL_SIZE:-50}
# Mock 登录(生产环境默认关闭,如需临时调试请在 .env 中显式设置为 true)
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
# 终端页面基础URL(用于NE2005等终端生成二维码)
- TERMINAL_BASE_URL=${TERMINAL_BASE_URL:-https://itsupport.servyou.com.cn/itterminal/}
# 服务配置
- BACKEND_HOST=0.0.0.0
- BACKEND_PORT=8000
# 上传文件目录(持久化)
- UPLOAD_DIR=/app/uploads
# 运行期日志目录(供"运行期日志"管理页面读取,需与下方 volumes 挂载一致)
- RUNTIME_LOG_DIR=/app/logs
# 安全告警(企微机器人 webhook)
- CONTENT_AUDIT_WEBHOOK=${CONTENT_AUDIT_WEBHOOK}
volumes:
# 代码热更新(生产环境:宿主机 ./app → 容器 /app/app
- ./app:/app/app
- backend-uploads:/app/uploads
- ${RUNTIME_LOG_HOST_DIR:-/var/log/wecom-it-desk}:/app/logs
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
neo4j:
condition: service_healthy
command: >
/bin/sh -c "
echo '>>> 启动 API 服务 (跳过迁移)...' &&
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 1
"
networks:
- it-desk-internal
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health').read()"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "5"
# --------------------------------------------------------------------------
# Nginx — 反向代理 + 静态文件服务
# --------------------------------------------------------------------------
nginx:
image: nginx:1.27-alpine
container_name: wecom_it_nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- ./frontend-h5/dist:/usr/share/nginx/html/itdesk:ro
- ./frontend-h5/dist:/usr/share/nginx/html/h5:ro
- ./frontend-agent/dist:/usr/share/nginx/html/itagent:ro
- ./frontend-admin/dist:/usr/share/nginx/html/itadmin:ro
- ./frontend-portal/dist:/usr/share/nginx/html/itportal:ro
- ./frontend-terminal/dist:/usr/share/nginx/html/itterminal:ro
depends_on:
- backend
networks:
- it-desk-internal
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:80/itdesk/health || exit 1"]
interval: 15s
timeout: 5s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# =============================================================================
# 网络
# =============================================================================
networks:
it-desk-internal:
driver: bridge
# =============================================================================
# 数据卷 — 持久化存储
# =============================================================================
volumes:
postgres_data:
name: wecom_it_postgres_data
redis_data:
name: wecom_it_redis_data
neo4j_data:
name: wecom_it_neo4j_data
neo4j_logs:
name: wecom_it_neo4j_logs
backend-uploads:
name: wecom_it_backend_uploads