44e77dcb0e
**重构前**(旧编号 02-11): - docs/02-产品需求/ → 00 产品规划/PRD - docs/03-技术架构/ → 01-05 子目录散落 - docs/04-原型设计/ → 01-02 产品设计(HTML 原型) - docs/05-原型设计/ → screens/ - docs/06-测试素材/ → 02-E2E / 03-功能 / 04-版本测试 - docs/07-项目管理/ → 任务说明书/日报/计划 - docs/08-安全审计/ → 审计报告 - docs/09-堡垒运维/ → toolbox / deploy - docs/10-项目管理/ → 任务说明书(重复) - docs/11-历史归档/ → deploy-nas-archived **重构后**(新编号 00-07,语义化): - docs/00-产品开发流程与文档管理规范.md - docs/00-版本迭代总览.md - docs/01-产品文档/ (PRD/原型/认证/会话/AI 服务/坐席/集成) - docs/02-技术文档/ (技术方案/架构图/重构记录/前端改造/实现配置) - docs/03-测试文档/ (E2E/功能用例/版本报告/缺陷单) - docs/04-运维文档/ (部署运维/运维指南) - docs/05-运营文档/ (品牌推广/用户手册) - docs/06-安全审计/ (审计报告) - docs/07-项目管理/ (任务说明书/日报/计划/看板) **净收益**: - 目录编号与产品文档管理规范对齐(按文档阶段 01-07 编号) - 消除 02-产品需求 与 10-项目管理 的编号重叠 - 子目录按文档类型分组(如 01-产品文档/00-产品规划、01-产品文档/01-认证与登录) - 把运维/安全/项目管理从 0X 散落改为 04/06/07 合计 494 文件 + 78495 行 / - 14076 行
203 lines
7.3 KiB
Plaintext
203 lines
7.3 KiB
Plaintext
# =============================================================================
|
||
# 企微IT智能服务台 — 群晖 NAS Docker Compose(含 Cloudflare Tunnel)
|
||
# =============================================================================
|
||
# 适用场景:群晖 NAS + Cloudflare Tunnel + 未认证企微
|
||
# 域名:itdesk.amanzac.com(通过 Cloudflare Tunnel 暴露到公网)
|
||
#
|
||
# 用法:
|
||
# 1. 先完成 Cloudflare Tunnel 创建,获取 token(见部署指南 §2)
|
||
# 2. 复制 .env.nas 为 .env 并填入 token 和企微配置
|
||
# 3. 在 NAS SSH 或 Container Manager 中启动:
|
||
# docker compose -f docker-compose.nas.yml up -d
|
||
#
|
||
# 架构:
|
||
# 互联网 → Cloudflare Edge → Cloudflare Tunnel → nginx:80 → { /itdesk/, /itagent/, /api/, /ws/ }
|
||
# =============================================================================
|
||
|
||
services:
|
||
# --------------------------------------------------------------------------
|
||
# Cloudflare Tunnel — 内网穿透,替代公网 IP + HTTPS
|
||
# --------------------------------------------------------------------------
|
||
# 原理:cloudflared 容器主动连接 Cloudflare Edge,建立反向隧道
|
||
# 无需开放任何端口,无需公网 IP,无需 SSL 证书
|
||
# 配置:在 Cloudflare Dashboard > Zero Trust > Networks > Tunnels 创建
|
||
# 获得 tunnel token 后填入 .env 的 CF_TUNNEL_TOKEN
|
||
# --------------------------------------------------------------------------
|
||
cloudflared:
|
||
image: cloudflare/cloudflared:latest
|
||
container_name: wecom_it_cloudflared
|
||
restart: unless-stopped
|
||
# --no-autoupdate 防止容器内自动更新导致重启
|
||
# token 从 Cloudflare Dashboard 获取
|
||
command: tunnel --no-autoupdate run
|
||
environment:
|
||
- TUNNEL_TOKEN=${CF_TUNNEL_TOKEN}
|
||
networks:
|
||
- it-desk-internal
|
||
depends_on:
|
||
- nginx
|
||
logging:
|
||
driver: "json-file"
|
||
options:
|
||
max-size: "10m"
|
||
max-file: "3"
|
||
|
||
# --------------------------------------------------------------------------
|
||
# 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:
|
||
# 群晖建议使用共享文件夹存储,便于备份
|
||
# 格式:/volume1/docker/wecom-it-desk/postgres:/var/lib/postgresql/data
|
||
- 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
|
||
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"
|
||
|
||
# --------------------------------------------------------------------------
|
||
# FastAPI 后端 — 核心业务服务
|
||
# --------------------------------------------------------------------------
|
||
backend:
|
||
build:
|
||
context: ./backend
|
||
dockerfile: Dockerfile
|
||
image: wecom-it-desk-backend:latest
|
||
container_name: wecom_it_backend
|
||
restart: unless-stopped
|
||
environment:
|
||
# 企微凭证(从 .env 文件读取)
|
||
- WECOM_CORP_ID=${WECOM_CORP_ID}
|
||
- WECOM_AGENT_ID=${WECOM_AGENT_ID}
|
||
- WECOM_SECRET=${WECOM_SECRET}
|
||
- WECOM_TOKEN=${WECOM_TOKEN}
|
||
- WECOM_ENCODING_AES_KEY=${WECOM_ENCODING_AES_KEY}
|
||
# 数据库(Docker 内部网络)
|
||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||
# Redis(Docker 内部网络)
|
||
- REDIS_URL=redis://redis:6379/0
|
||
# CORS(NAS 部署用 Cloudflare Tunnel 域名)
|
||
- CORS_ORIGINS=${CORS_ORIGINS:-https://itdesk.amanzac.com}
|
||
# AI 服务(Dify)— NAS 部署可能无法直连内网 Dify,留空则禁用 AI 功能
|
||
- DIFY_API_URL=${DIFY_API_URL:-}
|
||
- DIFY_API_KEY=${DIFY_API_KEY:-}
|
||
- DIFY_TIMEOUT=${DIFY_TIMEOUT:-30}
|
||
# 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}
|
||
# Mock 登录(测试阶段跳过 OAuth2)
|
||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||
# 服务配置
|
||
- BACKEND_HOST=0.0.0.0
|
||
- BACKEND_PORT=8000
|
||
depends_on:
|
||
postgres:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_healthy
|
||
command: >
|
||
/bin/sh -c "
|
||
echo '>>> 执行数据库迁移...' &&
|
||
cd /app && PYTHONPATH=/app alembic upgrade head &&
|
||
echo '>>> 启动 API 服务...' &&
|
||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2
|
||
"
|
||
networks:
|
||
- it-desk-internal
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
|
||
interval: 15s
|
||
timeout: 5s
|
||
retries: 3
|
||
start_period: 30s
|
||
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
|
||
# NAS 部署不需要映射端口到宿主机(Cloudflare Tunnel 直接连接容器网络)
|
||
# 但保留映射方便内网调试
|
||
ports:
|
||
- "18080:80"
|
||
volumes:
|
||
- ./nginx/nginx-nas.conf:/etc/nginx/nginx.conf:ro
|
||
- ./frontend-h5/dist:/usr/share/nginx/html/itdesk:ro
|
||
- ./frontend-agent/dist:/usr/share/nginx/html/itagent: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
|