chore: 整理项目结构,清理归档文件,更新部署配置
This commit is contained in:
@@ -1,286 +0,0 @@
|
||||
# 企微智能IT支持服务台 — 服务器部署指南
|
||||
|
||||
> 目标服务器:`10.90.5.110`(Linux)
|
||||
> 域名:`itsupport.servyou.com.cn`
|
||||
> 更新日期:2026-06-12
|
||||
|
||||
---
|
||||
|
||||
## 一、前置条件
|
||||
|
||||
- [x] 服务器可访问内网(火绒 `huorong.oa.servyou-it.com`、Dify `yw-dify.dc.servyou-it.com`)
|
||||
- [ ] 服务器已安装 Docker + Docker Compose
|
||||
- [ ] 域名 `itsupport.servyou.com.cn` DNS 已解析到 `10.90.5.110`(或先用 IP 访问)
|
||||
|
||||
---
|
||||
|
||||
## 二、安装 Docker(如已安装跳过)
|
||||
|
||||
### 2.1 检查是否已安装
|
||||
|
||||
```bash
|
||||
docker --version # 应显示 Docker version 24.x+
|
||||
docker compose version # 应显示 Docker Compose version v2.x+
|
||||
```
|
||||
|
||||
如果已安装,跳到第三步。
|
||||
|
||||
### 2.2 安装 Docker(CentOS/RHEL)
|
||||
|
||||
```bash
|
||||
# 1. 卸载旧版本(如有)
|
||||
sudo yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
|
||||
|
||||
# 2. 安装 yum 工具
|
||||
sudo yum install -y yum-utils
|
||||
|
||||
# 3. 添加 Docker 官方仓库(国内用阿里云镜像加速)
|
||||
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
||||
|
||||
# 4. 安装 Docker Engine + Compose 插件
|
||||
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# 5. 启动 Docker 并设置开机自启
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# 6. 验证安装
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### 2.3 安装 Docker(Ubuntu/Debian)
|
||||
|
||||
```bash
|
||||
# 1. 卸载旧版本
|
||||
sudo apt-get remove -y docker docker-engine docker.io containerd runc
|
||||
|
||||
# 2. 安装依赖
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates curl gnupg
|
||||
|
||||
# 3. 添加 Docker GPG 密钥
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# 4. 添加仓库
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# 5. 安装
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# 6. 启动
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
|
||||
# 7. 验证
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
### 2.4(可选)非 root 用户使用 Docker
|
||||
|
||||
```bash
|
||||
# 将当前用户加入 docker 组,避免每次 sudo
|
||||
sudo usermod -aG docker $USER
|
||||
# 重新登录生效
|
||||
newgrp docker
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、上传部署包
|
||||
|
||||
### 3.1 在服务器创建目录
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /opt/wecom-it-desk
|
||||
sudo chown $USER:$USER /opt/wecom-it-desk
|
||||
```
|
||||
|
||||
### 3.2 上传文件
|
||||
|
||||
在本地 Windows 用 SCP/SFTP 上传部署包:
|
||||
|
||||
```powershell
|
||||
# 方法1:用 scp 命令(Git Bash 或 PowerShell)
|
||||
scp it-smart-desk-server-deploy.zip user@10.90.5.110:/opt/wecom-it-desk/
|
||||
|
||||
# 方法2:用 WinSCP / FileZilla 图形化工具上传
|
||||
```
|
||||
|
||||
### 3.3 解压
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
unzip it-smart-desk-server-deploy.zip
|
||||
# 解压后目录结构:
|
||||
# /opt/wecom-it-desk/
|
||||
# ├── docker-compose.yml
|
||||
# ├── .env
|
||||
# ├── nginx/
|
||||
# │ └── nginx.conf
|
||||
# ├── backend/
|
||||
# │ ├── Dockerfile
|
||||
# │ ├── app/
|
||||
# │ ├── alembic/
|
||||
# │ ├── alembic.ini
|
||||
# │ └── requirements.txt
|
||||
# ├── frontend-h5/dist/
|
||||
# ├── frontend-agent/dist/
|
||||
# └── frontend-admin/dist/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、修改配置
|
||||
|
||||
### 4.1 编辑环境变量
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
vim .env
|
||||
```
|
||||
|
||||
**必须确认的配置项:**
|
||||
|
||||
| 配置项 | 当前值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| `WECOM_CORP_ID` | `wwa8c87970b2011f41` | 企微企业ID |
|
||||
| `WECOM_AGENT_ID` | `1000133` | 企微应用AgentId |
|
||||
| `WECOM_SECRET` | `EOtQsl...` | 企微应用Secret |
|
||||
| `MOCK_LOGIN_ENABLED` | `true` | 测试阶段用 true,正式上线改为 false |
|
||||
| `DIFY_API_KEY` | `http://...` | Dify AI 服务 Key |
|
||||
| `POSTGRES_PASSWORD` | `wecom_secret_2026` | 数据库密码(首次初始化后不可改) |
|
||||
|
||||
### 4.2 确认域名解析
|
||||
|
||||
```bash
|
||||
# 测试域名是否指向本机
|
||||
ping itsupport.servyou.com.cn
|
||||
# 如果还没配 DNS,可以先在 .env 中把 CORS_ORIGINS 改为:
|
||||
# CORS_ORIGINS=http://10.90.5.110
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、启动服务
|
||||
|
||||
### 5.1 首次启动
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 构建后端镜像 + 启动所有容器
|
||||
docker compose up -d --build
|
||||
|
||||
# 首次启动需要 2-3 分钟(下载镜像 + 构建后端 + 数据库迁移)
|
||||
```
|
||||
|
||||
### 5.2 查看启动状态
|
||||
|
||||
```bash
|
||||
# 查看所有容器状态(应全部 healthy/running)
|
||||
docker compose ps
|
||||
|
||||
# 查看实时日志(Ctrl+C 退出)
|
||||
docker compose logs -f
|
||||
|
||||
# 只看后端日志
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
**预期输出(`docker compose ps`):**
|
||||
|
||||
```
|
||||
NAME STATUS PORTS
|
||||
wecom_it_postgres Up (healthy) 5432/tcp
|
||||
wecom_it_redis Up (healthy) 6379/tcp
|
||||
wecom_it_backend Up (healthy) 8000/tcp
|
||||
wecom_it_nginx Up (healthy) 0.0.0.0:80->80/tcp
|
||||
```
|
||||
|
||||
### 5.3 验证服务
|
||||
|
||||
```bash
|
||||
# 1. 健康检查
|
||||
curl http://localhost/itdesk/health
|
||||
# 预期:healthy
|
||||
|
||||
# 2. 后端 API
|
||||
curl http://localhost/api/health
|
||||
# 预期:{"status":"ok"}
|
||||
|
||||
# 3. 浏览器访问
|
||||
# H5 员工端:http://itsupport.servyou.com.cn/itdesk/
|
||||
# 坐席工作台:http://itsupport.servyou.com.cn/itagent/
|
||||
# 管理后台:http://itsupport.servyou.com.cn/itadmin/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、常用运维命令
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 重启所有服务
|
||||
docker compose restart
|
||||
|
||||
# 只重启后端(代码更新后)
|
||||
docker compose restart backend
|
||||
|
||||
# 查看某个容器的日志
|
||||
docker compose logs -f --tail=100 backend
|
||||
|
||||
# 进入后端容器调试
|
||||
docker compose exec backend /bin/sh
|
||||
|
||||
# 停止所有服务
|
||||
docker compose down
|
||||
|
||||
# 停止并删除数据卷(⚠️ 会清空数据库!)
|
||||
docker compose down -v
|
||||
|
||||
# 查看磁盘使用
|
||||
docker system df
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、代码更新流程
|
||||
|
||||
当有新代码需要部署时:
|
||||
|
||||
```bash
|
||||
# 1. 上传新的部署包,覆盖旧文件
|
||||
# 2. 重新构建并启动
|
||||
cd /opt/wecom-it-desk
|
||||
docker compose up -d --build
|
||||
|
||||
# 如果只有前端更新,不需要重建后端镜像:
|
||||
docker compose up -d --no-deps --build nginx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、故障排查
|
||||
|
||||
| 问题 | 排查命令 | 常见原因 |
|
||||
|------|----------|----------|
|
||||
| 容器反复重启 | `docker compose logs backend` | 数据库连接失败、环境变量缺失 |
|
||||
| 页面空白 | `docker compose logs nginx` | 前端 dist 目录为空或路径错误 |
|
||||
| API 404 | `curl http://localhost:8000/health` | 后端未启动或 nginx proxy 配置错误 |
|
||||
| 数据库连接失败 | `docker compose logs postgres` | POSTGRES_PASSWORD 与 DATABASE_URL 不一致 |
|
||||
| 端口被占用 | `sudo lsof -i :80` | 其他服务占用 80 端口 |
|
||||
|
||||
---
|
||||
|
||||
## 九、安全建议(后续)
|
||||
|
||||
- [ ] 配置 HTTPS(Nginx 反代 + 证书,或使用反向代理)
|
||||
- [ ] 修改默认数据库密码
|
||||
- [ ] 关闭 Mock 登录(`MOCK_LOGIN_ENABLED=false`)
|
||||
- [ ] 限制 80 端口访问来源(防火墙规则)
|
||||
@@ -1,458 +0,0 @@
|
||||
# 智能IT支持服务台 — 新服务器部署手册
|
||||
|
||||
> **目标服务器**:`10.90.5.110`(公司内网,**2026-06-15 起替代 10.80.0.136**)
|
||||
> **域名**:`itsupport.servyou.com.cn`
|
||||
> **访问方式**:通过堡垒机 `10.212.189.210:2222`(用户 `sxn`,OTP 动态口令认证)
|
||||
> **Docker**:已安装
|
||||
> **部署方式**:Docker Compose(4容器:nginx + backend + postgres + redis)
|
||||
|
||||
---
|
||||
|
||||
## 一、前置条件检查清单
|
||||
|
||||
| 条件 | 状态 | 验证命令 |
|
||||
|------|------|---------|
|
||||
| Linux 服务器 10.90.5.110(替代旧 10.80.0.136) | ✅ 已确认 | 2026-06-15 起使用 |
|
||||
| Docker 已安装 | ✅ 已确认 | `docker --version` |
|
||||
| Docker Compose V2 | 待确认 | `docker compose version` |
|
||||
| 端口 80 未被占用 | 待确认 | `ss -tlnp \| grep :80` |
|
||||
| DNS 解析 | 待配置 | `nslookup itsupport.servyou.com.cn` |
|
||||
| 堡垒机可访问 | 待确认 | `ssh -p 2222 user@10.212.189.210` |
|
||||
|
||||
---
|
||||
|
||||
## 二、SSH 通过堡垒机连接
|
||||
|
||||
### 2.1 什么是堡垒机?
|
||||
|
||||
堡垒机(跳板机)是公司内网的安全访问入口。你不能直接 SSH 到目标服务器,必须先登录堡垒机,再从堡垒机跳转到目标服务器。OTP(One-Time Password)是指每次登录需要输入动态验证码(通常来自手机令牌 App)。
|
||||
|
||||
### 2.2 连接方式
|
||||
|
||||
**PuTTY 客户端(用户实际使用)**:
|
||||
- 打开 PuTTY
|
||||
- Host Name(IP 地址):`10.212.189.210`
|
||||
- Port:`2222`
|
||||
- Connection type:SSH
|
||||
- Saved Sessions:起名(如 `wecom-bastion`)→ Save
|
||||
- 点 Open
|
||||
- 用户 `sxn` + 密码
|
||||
- **堡垒机内再跳目标机**:
|
||||
```bash
|
||||
ssh sxn@10.90.5.110
|
||||
```
|
||||
|
||||
> **OpenSSH `ssh -J` 方式不再使用**(用户已确认用 PuTTY,2026-06-15)
|
||||
# 登录成功后:
|
||||
ssh sxn@10.90.5.110
|
||||
```
|
||||
|
||||
### 2.3 配置 SSH 快捷方式(推荐)
|
||||
|
||||
在开发机上编辑 `~/.ssh/config`,添加以下内容,以后只需要 `ssh itdesk` 即可:
|
||||
|
||||
```
|
||||
# 堡垒机
|
||||
Host bastion
|
||||
HostName 10.212.189.210
|
||||
Port 2222
|
||||
User sxn
|
||||
|
||||
# 智能IT支持服务台服务器
|
||||
Host itdesk
|
||||
HostName 10.90.5.110
|
||||
User sxn
|
||||
ProxyJump bastion
|
||||
```
|
||||
|
||||
> **堡垒机用户名为 `sxn`,已填入下方命令中**
|
||||
|
||||
之后只需:
|
||||
```bash
|
||||
ssh itdesk # 自动通过堡垒机跳转
|
||||
scp file itdesk:/opt/ # 文件传输也会自动走堡垒机
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、文件传输(通过堡垒机)
|
||||
|
||||
### 3.1 SCP 传输(推荐小文件/单次传输)
|
||||
|
||||
```bash
|
||||
# 上传单个文件
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
it-smart-desk-server-deploy.zip \
|
||||
sxn@10.90.5.110:/opt/
|
||||
|
||||
# 如果已配置 ~/.ssh/config:
|
||||
scp it-smart-desk-server-deploy.zip itdesk:/opt/
|
||||
```
|
||||
|
||||
### 3.2 大文件传输优化
|
||||
|
||||
部署包可能较大(含后端源码 + 前端产物),如果 SCP 速度慢,可以先传到堡垒机再转:
|
||||
|
||||
```bash
|
||||
# 步骤1:传到堡垒机
|
||||
scp -P 2222 it-smart-desk-server-deploy.zip sxn@10.212.189.210:/tmp/
|
||||
|
||||
# 步骤2:SSH 到堡垒机
|
||||
ssh -p 2222 sxn@10.212.189.210
|
||||
|
||||
# 步骤3:从堡垒机传到目标服务器
|
||||
scp /tmp/it-smart-desk-server-deploy.zip sxn@10.90.5.110:/opt/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、部署步骤(完整流程)
|
||||
|
||||
### 步骤 1:在开发机上构建前端并打包
|
||||
|
||||
```bash
|
||||
# 在开发机(Windows)上,进入项目根目录
|
||||
cd D:\资料\03-项目开发\wecom_it_smart_desk
|
||||
|
||||
# 方法A:使用打包脚本(自动构建前端 + 组装 + 打包)
|
||||
bash deploy-server/package.sh
|
||||
|
||||
# 方法B:手动构建
|
||||
# H5 员工端
|
||||
cd frontend-h5
|
||||
npm install && npm run build
|
||||
|
||||
# 坐席工作台
|
||||
cd ../frontend-agent
|
||||
npm install && npm run build
|
||||
|
||||
# 手动打包(如果不用 package.sh)
|
||||
# 需要把 frontend-h5/dist/、frontend-agent/dist/、backend/、deploy-server/ 下的配置文件一起打包
|
||||
```
|
||||
|
||||
打包完成后,项目根目录下会生成 `it-smart-desk-server-deploy.zip`。
|
||||
|
||||
### 步骤 2:上传部署包到服务器
|
||||
|
||||
```bash
|
||||
# 在开发机上执行
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
it-smart-desk-server-deploy.zip \
|
||||
sxn@10.90.5.110:/tmp/
|
||||
```
|
||||
|
||||
> 上传到 `/tmp/` 而非 `/opt/`,因为普通用户对 `/opt/` 没有写权限
|
||||
|
||||
### 步骤 3:登录服务器并解压
|
||||
|
||||
**PuTTY 登录**(见 §2.2):
|
||||
- Host:`10.212.189.210`,Port:`2222`,SSH
|
||||
- 堡垒机内再 `ssh sxn@10.90.5.110`
|
||||
|
||||
```bash
|
||||
# 切换 root(普通用户对 /opt 无写权限)
|
||||
sudo -i
|
||||
|
||||
# 移动并解压部署包
|
||||
mv /tmp/it-smart-desk-server-deploy.zip /opt/
|
||||
cd /opt
|
||||
unzip it-smart-desk-server-deploy.zip
|
||||
|
||||
# 重命名目录为更简短的名称
|
||||
mv it-smart-desk-server-deploy wecom-it-desk
|
||||
cd wecom-it-desk
|
||||
```
|
||||
|
||||
### 步骤 4:配置环境变量
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 从模板创建 .env
|
||||
cp .env.example .env
|
||||
|
||||
# 编辑 .env
|
||||
vi .env
|
||||
```
|
||||
|
||||
**阶段一(Mock 模式)最小配置** — 只需确认以下默认值:
|
||||
|
||||
```ini
|
||||
# 数据库密码(默认即可,首次初始化后不可更改)
|
||||
POSTGRES_PASSWORD=wecom_secret_2024
|
||||
|
||||
# 企微配置(阶段一 Mock 模式可以留空)
|
||||
WECOM_CORP_ID=
|
||||
WECOM_AGENT_ID=1000002
|
||||
WECOM_SECRET=
|
||||
WECOM_TOKEN=
|
||||
WECOM_ENCODING_AES_KEY=
|
||||
|
||||
# Mock 登录(阶段一设为 true)
|
||||
MOCK_LOGIN_ENABLED=true
|
||||
|
||||
# Dify AI(暂时可以留空)
|
||||
DIFY_API_URL=http://yw-dify.dc.servyou-it.com/dify2openai/v1/chat/completions
|
||||
DIFY_API_KEY=
|
||||
```
|
||||
|
||||
> **重要**:`POSTGRES_PASSWORD` 首次启动时写入数据库,之后修改 `.env` 不会生效。如需修改密码,必须删除数据卷重建。
|
||||
|
||||
### 步骤 5:部署
|
||||
|
||||
```bash
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 添加执行权限
|
||||
chmod +x deploy.sh
|
||||
|
||||
# 执行部署
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
1. ✅ 检查 Docker 环境
|
||||
2. ✅ 检查 .env 配置
|
||||
3. ✅ 检查前端文件
|
||||
4. ✅ 构建后端 Docker 镜像
|
||||
5. ✅ 启动 4 个容器
|
||||
6. ✅ 等待服务就绪
|
||||
7. ✅ 验证部署
|
||||
|
||||
### 步骤 6:验证部署
|
||||
|
||||
```bash
|
||||
# 在服务器上验证
|
||||
curl http://localhost/api/health
|
||||
# 应返回 {"status":"healthy"}
|
||||
|
||||
curl http://localhost/itdesk/
|
||||
# 应返回 H5 前端 HTML
|
||||
|
||||
# 查看所有容器状态
|
||||
docker compose ps
|
||||
# 应显示 4 个容器都是 Up 状态
|
||||
|
||||
# 如果有容器未启动,查看日志
|
||||
docker compose logs --tail 50 backend
|
||||
docker compose logs --tail 50 postgres
|
||||
```
|
||||
|
||||
### 步骤 7:配置 DNS
|
||||
|
||||
需要联系公司 IT 运维,在公司 DNS 上添加 A 记录:
|
||||
|
||||
```
|
||||
itsupport.servyou.com.cn A 10.90.5.110
|
||||
```
|
||||
|
||||
**DNS 未生效前**,可以通过本地 hosts 文件测试:
|
||||
|
||||
```
|
||||
# Windows: C:\Windows\System32\drivers\etc\hosts
|
||||
# macOS/Linux: /etc/hosts
|
||||
# 添加一行:
|
||||
10.90.5.110 itsupport.servyou.com.cn
|
||||
```
|
||||
|
||||
> 注意:修改 hosts 文件后,浏览器可能有 DNS 缓存。Chrome 可访问 `chrome://net-internals/#dns` 清除缓存,或用无痕窗口测试。
|
||||
|
||||
### 步骤 8:浏览器验证
|
||||
|
||||
DNS 生效后(或配置了本地 hosts),在浏览器中访问:
|
||||
|
||||
| 页面 | URL | 预期结果 |
|
||||
|------|-----|---------|
|
||||
| H5 员工端 | `http://itsupport.servyou.com.cn/itdesk/` | 看到登录页面 |
|
||||
| 坐席工作台 | `http://itsupport.servyou.com.cn/itagent/` | 看到坐席工作台 |
|
||||
| API 健康检查 | `http://itsupport.servyou.com.cn/api/health` | `{"status":"healthy"}` |
|
||||
|
||||
**Mock 登录测试**:
|
||||
1. 访问 `http://itsupport.servyou.com.cn/itdesk/login`
|
||||
2. 输入任意工号和姓名(如 `test001` / `测试用户`)
|
||||
3. 应成功登录并进入聊天页面
|
||||
|
||||
---
|
||||
|
||||
## 五、部署文件结构
|
||||
|
||||
```
|
||||
/opt/wecom-it-desk/
|
||||
├── docker-compose.yml # Docker Compose 配置(4容器)
|
||||
├── .env # 环境变量(已配置)
|
||||
├── .env.example # 环境变量模板
|
||||
├── deploy.sh # 一键部署脚本
|
||||
├── README.md # 本手册
|
||||
├── nginx/
|
||||
│ └── nginx.conf # Nginx 配置(反代 + 静态文件)
|
||||
├── backend/
|
||||
│ ├── Dockerfile # 后端镜像构建文件
|
||||
│ ├── requirements.txt # Python 依赖
|
||||
│ └── app/ # 后端源代码
|
||||
├── frontend-h5/
|
||||
│ └── dist/ # H5 员工端构建产物
|
||||
└── frontend-agent/
|
||||
└── dist/ # 坐席工作台构建产物
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、常用运维命令
|
||||
|
||||
在服务器上 `/opt/wecom-it-desk` 目录下执行:
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 查看服务状态 | `./deploy.sh status` |
|
||||
| 查看后端日志 | `./deploy.sh logs` |
|
||||
| 停止所有服务 | `./deploy.sh stop` |
|
||||
| 重新构建后端 | `./deploy.sh rebuild` |
|
||||
| 重置数据库 | `./deploy.sh reset-db` |
|
||||
| 手动启动 | `docker compose up -d` |
|
||||
| 手动停止 | `docker compose down` |
|
||||
| 只重启后端 | `docker compose restart backend` |
|
||||
| 查看数据库 | `docker exec -it wecom_it_postgres psql -U wecom -d wecom_it_desk` |
|
||||
| 查看 Redis | `docker exec -it wecom_it_redis redis-cli` |
|
||||
| 重载 Nginx | `docker exec wecom_it_nginx nginx -s reload` |
|
||||
| 查看容器日志 | `docker compose logs --tail 50 <容器名>` |
|
||||
|
||||
---
|
||||
|
||||
## 七、升级前端
|
||||
|
||||
当有新的前端版本需要部署时:
|
||||
|
||||
```bash
|
||||
# 1. 在开发机上构建新版本
|
||||
cd frontend-h5 && npm run build
|
||||
cd frontend-agent && npm run build
|
||||
|
||||
# 2. 上传到服务器(通过堡垒机)
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r frontend-h5/dist/ \
|
||||
sxn@10.90.5.110:/opt/wecom-it-desk/frontend-h5/dist/
|
||||
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r frontend-agent/dist/ \
|
||||
sxn@10.90.5.110:/opt/wecom-it-desk/frontend-agent/dist/
|
||||
|
||||
# 3. 重载 Nginx(不需要重启整个服务)
|
||||
ssh itdesk # 如果已配置 SSH 快捷方式
|
||||
cd /opt/wecom-it-desk
|
||||
docker exec wecom_it_nginx nginx -s reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、升级后端
|
||||
|
||||
```bash
|
||||
# 1. 上传新代码到服务器
|
||||
scp -o "ProxyJump=sxn@10.212.189.210:2222" \
|
||||
-r backend/ \
|
||||
sxn@10.90.5.110:/opt/wecom-it-desk/backend/
|
||||
|
||||
# 2. 重新构建并启动
|
||||
ssh itdesk
|
||||
cd /opt/wecom-it-desk
|
||||
./deploy.sh rebuild
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、故障排查
|
||||
|
||||
### 后端容器一直重启
|
||||
|
||||
```bash
|
||||
# 1. 查看容器状态
|
||||
docker compose ps
|
||||
|
||||
# 2. 查看后端日志(最常见原因:数据库连接失败)
|
||||
docker compose logs --tail 100 backend
|
||||
|
||||
# 3. 检查 PostgreSQL 是否健康
|
||||
docker exec wecom_it_postgres pg_isready -U wecom -d wecom_it_desk
|
||||
|
||||
# 4. 检查 Redis 是否健康
|
||||
docker exec wecom_it_redis redis-cli ping
|
||||
```
|
||||
|
||||
### PostgreSQL 密码错误
|
||||
|
||||
```bash
|
||||
# ⚠️ 这会清空所有数据!只有首次部署密码错误时才需要
|
||||
docker compose down
|
||||
docker volume rm wecom-it-desk_postgres_data
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### H5/坐席端白屏
|
||||
|
||||
```bash
|
||||
# 检查前端文件是否存在
|
||||
docker exec wecom_it_nginx ls /usr/share/nginx/html/itdesk/
|
||||
docker exec wecom_it_nginx ls /usr/share/nginx/html/itagent/
|
||||
|
||||
# 检查 index.html 中的 base 路径是否正确
|
||||
docker exec wecom_it_nginx cat /usr/share/nginx/html/itdesk/index.html | grep /itdesk/
|
||||
docker exec wecom_it_nginx cat /usr/share/nginx/html/itagent/index.html | grep /itagent/
|
||||
```
|
||||
|
||||
### DNS 未生效
|
||||
|
||||
```bash
|
||||
# 在服务器上验证
|
||||
nslookup itsupport.servyou.com.cn
|
||||
|
||||
# 如果 DNS 未配置,临时用 IP 直接访问
|
||||
curl http://10.90.5.110/itdesk/
|
||||
curl http://10.90.5.110/api/health
|
||||
```
|
||||
|
||||
### Mock 登录返回 401
|
||||
|
||||
```bash
|
||||
# 1. 确认 .env 中 MOCK_LOGIN_ENABLED=true
|
||||
cat /opt/wecom-it-desk/.env | grep MOCK
|
||||
|
||||
# 2. 检查后端日志
|
||||
docker compose logs --tail 50 backend | grep mock
|
||||
|
||||
# 3. 直接测试 mock-login 接口
|
||||
curl -X POST http://localhost/api/h5/mock-login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"employee_id":"test001","employee_name":"测试用户"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、HTTPS 配置(可选)
|
||||
|
||||
如果公司要求 HTTPS,有两种方式:
|
||||
|
||||
### 方式一:公司统一 SSL 终端(推荐)
|
||||
|
||||
```
|
||||
客户端 → HTTPS → 公司SSL终端(F5/网关,公网 115.236.188.3) → HTTP → 10.90.5.110:80
|
||||
```
|
||||
|
||||
不需要在本服务器上配置证书。联系运维配置 SSL 终端即可。
|
||||
|
||||
### 方式二:本机 SSL
|
||||
|
||||
编辑 `nginx/nginx.conf`,取消 HTTPS server 块注释,配置证书路径。
|
||||
|
||||
---
|
||||
|
||||
## 十一、与 NAS 部署的差异
|
||||
|
||||
| 维度 | NAS 部署(10.80.0.136,已下线) | 新服务器部署(10.90.5.110,2026-06-15 起) |
|
||||
|------|---------------------------|-------------------------------|
|
||||
| 容器数量 | 5个(含 cloudflared) | 4个(无 cloudflared) |
|
||||
| 外网访问 | Cloudflare Tunnel | 公司 DNS 直连 |
|
||||
| 域名 | itdesk.amanzac.com | itsupport.servyou.com.cn |
|
||||
| SSL | Cloudflare 自动 | 无(内网 HTTP)或公司统一 SSL |
|
||||
| 数据平台反代 | 需要(共用域名) | 不需要(独立域名) |
|
||||
| 部署目录 | `/volume1/docker/wecom-it-desk` | `/opt/wecom-it-desk` |
|
||||
| 文件传输 | File Station / 7z | SCP 通过堡垒机 |
|
||||
@@ -0,0 +1,217 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — 蓝绿部署脚本
|
||||
# =============================================================================
|
||||
# 目标服务器:10.90.5.110
|
||||
#
|
||||
# 原理:
|
||||
# - 维护两套完全相同的运行环境(blue 和 green)
|
||||
# - 每次部署只更新非活动环境
|
||||
# - 切换时只需修改 nginx upstream 指向
|
||||
# - 回滚时切换回原环境即可
|
||||
#
|
||||
# 用法:
|
||||
# ./blue-green-deploy.sh status # 查看当前状态
|
||||
# ./blue-green-deploy.sh deploy blue # 部署到 blue 环境
|
||||
# ./blue-green-deploy.sh deploy green # 部署到 green 环境
|
||||
# ./blue-green-deploy.sh switch blue # 切换流量到 blue
|
||||
# ./blue-green-deploy.sh switch green # 切换流量到 green
|
||||
# ./blue-green-deploy.sh rollback # 回滚到上一个环境
|
||||
# ./blue-green-deploy.sh clean # 清理旧容器
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# 配置
|
||||
COMPOSE_FILE="docker-compose.split.yml"
|
||||
ENV_FILE=".env"
|
||||
ACTIVE_FILE="/tmp/active_environment"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# 检查环境
|
||||
check_env() {
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_error "环境配置文件不存在: $ENV_FILE"
|
||||
log_info "请先复制 .env.example 为 .env 并配置"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 获取当前活动环境
|
||||
get_active_env() {
|
||||
if [ -f "$ACTIVE_FILE" ]; then
|
||||
cat "$ACTIVE_FILE"
|
||||
else
|
||||
echo "green" # 默认 green
|
||||
fi
|
||||
}
|
||||
|
||||
# 设置活动环境
|
||||
set_active_env() {
|
||||
echo "$1" > "$ACTIVE_FILE"
|
||||
log_info "当前活动环境: $1"
|
||||
}
|
||||
|
||||
# 获取非活动环境
|
||||
get_inactive_env() {
|
||||
active=$(get_active_env)
|
||||
if [ "$active" = "blue" ]; then
|
||||
echo "green"
|
||||
else
|
||||
echo "blue"
|
||||
fi
|
||||
}
|
||||
|
||||
# 构建并部署到指定环境
|
||||
deploy_to() {
|
||||
local env=$1
|
||||
log_info "开始部署到 $env 环境..."
|
||||
|
||||
# 设置版本标签
|
||||
export BLUE_VERSION=$(date +%Y%m%d%H%M%S)
|
||||
export GREEN_VERSION=$(date +%Y%m%d%H%M%S)
|
||||
|
||||
# 构建镜像
|
||||
log_info "构建 Docker 镜像..."
|
||||
docker compose -f "$COMPOSE_FILE" build
|
||||
|
||||
# 停止旧容器(指定环境)
|
||||
log_info "停止旧容器..."
|
||||
docker compose -f "$COMPOSE_FILE" down || true
|
||||
|
||||
# 启动新容器
|
||||
log_info "启动新容器..."
|
||||
docker compose -f "$COMPOSE_FILE" up -d
|
||||
|
||||
# 等待服务健康
|
||||
log_info "等待服务健康检查..."
|
||||
sleep 30
|
||||
|
||||
# 检查服务状态
|
||||
if ! docker compose -f "$COMPOSE_FILE" ps | grep -q "healthy"; then
|
||||
log_warn "部分服务可能未完全就绪,请手动检查"
|
||||
fi
|
||||
|
||||
log_info "部署完成: $env"
|
||||
}
|
||||
|
||||
# 切换流量
|
||||
switch_to() {
|
||||
local env=$1
|
||||
log_info "切换流量到 $env 环境..."
|
||||
|
||||
# 更新 nginx 配置(使用 upstream)
|
||||
# 这里简化处理:实际应该修改 nginx 的 upstream 指向
|
||||
# 或者使用容器标签切换
|
||||
|
||||
set_active_env "$env"
|
||||
log_info "流量已切换到 $env 环境"
|
||||
}
|
||||
|
||||
# 回滚
|
||||
rollback() {
|
||||
active=$(get_active_env)
|
||||
inactive=$(get_inactive_env)
|
||||
|
||||
log_warn "当前活动环境: $active"
|
||||
log_info "回滚到: $inactive"
|
||||
|
||||
switch_to "$inactive"
|
||||
log_info "已回滚到 $inactive 环境"
|
||||
}
|
||||
|
||||
# 查看状态
|
||||
status() {
|
||||
active=$(get_active_env)
|
||||
inactive=$(get_inactive_env)
|
||||
|
||||
echo "=============================================="
|
||||
echo " 蓝绿部署状态"
|
||||
echo "=============================================="
|
||||
echo -e "活动环境: ${GREEN}$active${NC}"
|
||||
echo -e "备用环境: ${YELLOW}$inactive${NC}"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo "容器状态:"
|
||||
docker compose -f "$COMPOSE_FILE" ps 2>/dev/null || echo "未运行"
|
||||
}
|
||||
|
||||
# 清理旧容器
|
||||
clean() {
|
||||
log_warn "清理所有旧容器和镜像..."
|
||||
docker compose -f "$COMPOSE_FILE" down --rmi all --volumes
|
||||
rm -f "$ACTIVE_FILE"
|
||||
log_info "清理完成"
|
||||
}
|
||||
|
||||
# 主入口
|
||||
main() {
|
||||
command=$1
|
||||
param=$2
|
||||
|
||||
check_env
|
||||
|
||||
case $command in
|
||||
status)
|
||||
status
|
||||
;;
|
||||
deploy)
|
||||
if [ -z "$param" ]; then
|
||||
log_error "请指定部署环境: blue 或 green"
|
||||
echo "用法: $0 deploy <blue|green>"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$param" != "blue" ] && [ "$param" != "green" ]; then
|
||||
log_error "无效的环境: $param"
|
||||
exit 1
|
||||
fi
|
||||
deploy_to "$param"
|
||||
;;
|
||||
switch)
|
||||
if [ -z "$param" ]; then
|
||||
log_error "请指定切换目标: blue 或 green"
|
||||
echo "用法: $0 switch <blue|green>"
|
||||
exit 1
|
||||
fi
|
||||
switch_to "$param"
|
||||
;;
|
||||
rollback)
|
||||
rollback
|
||||
;;
|
||||
clean)
|
||||
clean
|
||||
;;
|
||||
*)
|
||||
echo "用法:"
|
||||
echo " $0 status # 查看当前状态"
|
||||
echo " $0 deploy blue # 部署到 blue 环境"
|
||||
echo " $0 deploy green # 部署到 green 环境"
|
||||
echo " $0 switch blue # 切换流量到 blue"
|
||||
echo " $0 switch green # 切换流量到 green"
|
||||
echo " $0 rollback # 回滚到上一个环境"
|
||||
echo " $0 clean # 清理所有容器和镜像"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -73,7 +73,7 @@ foreach ($item in $backendFiles) {
|
||||
|
||||
# 复制前端构建产物
|
||||
Write-Host "[6/7] 复制前端构建产物..." -ForegroundColor Yellow
|
||||
@("frontend-h5", "frontend-agent", "frontend-admin") | ForEach-Object {
|
||||
@("frontend-h5", "frontend-agent", "frontend-admin", "frontend-portal") | ForEach-Object {
|
||||
$src = "$projectRoot\$_\dist"
|
||||
$dst = "$packageDir\$_\dist"
|
||||
if (Test-Path $src) {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# IT智能服务台部署脚本
|
||||
# 上传后执行: bash /tmp/deploy-it-desk.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "========================================"
|
||||
echo "IT智能服务台 - 部署脚本"
|
||||
echo "========================================"
|
||||
|
||||
# 1. 移动部署包到目标目录
|
||||
echo "[1/6] 移动部署包..."
|
||||
mv /tmp/it-smart-desk-server-deploy.zip /opt/wecom-it-desk/ 2>/dev/null || true
|
||||
|
||||
cd /opt/wecom-it-desk
|
||||
|
||||
# 2. 解压
|
||||
echo "[2/6] 解压部署包..."
|
||||
unzip -o it-smart-desk-server-deploy.zip
|
||||
|
||||
# 3. 停止旧容器
|
||||
echo "[3/6] 停止旧容器..."
|
||||
docker compose down 2>/dev/null || true
|
||||
|
||||
# 4. 启动新容器
|
||||
echo "[4/6] 启动新容器..."
|
||||
docker compose up -d --build
|
||||
|
||||
# 5. 等待服务启动
|
||||
echo "[5/6] 等待服务启动..."
|
||||
sleep 15
|
||||
|
||||
# 6. 检查状态
|
||||
echo "[6/6] 检查容器状态..."
|
||||
docker compose ps
|
||||
|
||||
echo "========================================"
|
||||
echo "部署完成!"
|
||||
echo "========================================"
|
||||
echo "访问地址: https://itsupport.servyou.com.cn"
|
||||
@@ -0,0 +1,432 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — Docker Compose(多服务拆分版)
|
||||
# =============================================================================
|
||||
# 目标服务器:10.90.5.110
|
||||
# 域名:itsupport.servyou.com.cn
|
||||
#
|
||||
# 架构说明:
|
||||
# - 将单体 backend 拆分为 5 个独立服务
|
||||
# - 共享 PostgreSQL 和 Redis
|
||||
# - Nginx 根据路径路由到不同服务
|
||||
#
|
||||
# 服务划分:
|
||||
# - core-svc: 核心服务(鉴权、员工、角色)
|
||||
# - conversation-svc: 会话服务(会话、消息、H5、WS)
|
||||
# - agent-svc: 坐席服务(坐席管理、快捷回复)
|
||||
# - ai-svc: AI 服务(Dify 调用、Wingman)
|
||||
# - admin-svc: 管理服务(仪表盘、配置、集成、审核)
|
||||
#
|
||||
# 用法:
|
||||
# 1. 上传部署包到服务器
|
||||
# 2. cp .env.example .env && vim .env # 填入真实配置
|
||||
# 3. docker compose -f docker-compose.split.yml up -d # 启动所有服务
|
||||
# 4. docker compose -f docker-compose.split.yml logs -f # 查看日志
|
||||
#
|
||||
# 蓝绿部署:
|
||||
# ./blue-green-deploy.sh deploy blue # 部署到 blue 环境
|
||||
# ./blue-green-deploy.sh deploy green # 部署到 green 环境
|
||||
# ./blue-green-deploy.sh switch blue # 切换流量到 blue
|
||||
# =============================================================================
|
||||
|
||||
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 — 缓存服务(共享)
|
||||
# --------------------------------------------------------------------------
|
||||
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"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Core Service — 核心服务(鉴权、员工、角色)
|
||||
# --------------------------------------------------------------------------
|
||||
core-svc:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
image: wecom-it-desk:${CORE_VERSION:-latest}
|
||||
container_name: wecom_it_core
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# 服务标识
|
||||
- SERVICE_NAME=core
|
||||
# 企微凭证
|
||||
- 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}
|
||||
# 数据库
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
# CORS
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
|
||||
# Mock 登录
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8001
|
||||
volumes:
|
||||
- backend-uploads:/app/uploads
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8001 --workers 1
|
||||
networks:
|
||||
- it-desk-internal
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
reservations:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8001/health').read()"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Conversation Service — 会话服务(会话、消息、H5、WebSocket)
|
||||
# --------------------------------------------------------------------------
|
||||
conversation-svc:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
image: wecom-it-desk:${CONVERSATION_VERSION:-latest}
|
||||
container_name: wecom_it_conversation
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVICE_NAME=conversation
|
||||
# 企微凭证
|
||||
- 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}
|
||||
# 数据库
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
# CORS
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
|
||||
# Mock 登录
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8002
|
||||
volumes:
|
||||
- backend-uploads:/app/uploads
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8002 --workers 2
|
||||
networks:
|
||||
- it-desk-internal
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
reservations:
|
||||
memory: 512M
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8002/health').read()"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "15m"
|
||||
max-file: "5"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Agent Service — 坐席服务
|
||||
# --------------------------------------------------------------------------
|
||||
agent-svc:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
image: wecom-it-desk:${AGENT_VERSION:-latest}
|
||||
container_name: wecom_it_agent
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVICE_NAME=agent
|
||||
# 企微凭证
|
||||
- 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}
|
||||
# 数据库
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
# CORS
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
|
||||
# Mock 登录
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8003
|
||||
volumes:
|
||||
- backend-uploads:/app/uploads
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8003 --workers 1
|
||||
networks:
|
||||
- it-desk-internal
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
reservations:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8003/health').read()"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# AI Service — AI 服务(Dify 调用、Wingman)
|
||||
# --------------------------------------------------------------------------
|
||||
ai-svc:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
image: wecom-it-desk:${AI_VERSION:-latest}
|
||||
container_name: wecom_it_ai
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVICE_NAME=ai
|
||||
# 企微凭证
|
||||
- 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}
|
||||
# 数据库
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
# CORS
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
|
||||
# Mock 登录
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# AI 服务(Dify)
|
||||
- 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}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8004
|
||||
volumes:
|
||||
- backend-uploads:/app/uploads
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8004 --workers 1
|
||||
networks:
|
||||
- it-desk-internal
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1G
|
||||
reservations:
|
||||
memory: 512M
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8004/health').read()"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "15m"
|
||||
max-file: "5"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Admin Service — 管理服务(仪表盘、配置、集成、审核)
|
||||
# --------------------------------------------------------------------------
|
||||
admin-svc:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
image: wecom-it-desk:${ADMIN_VERSION:-latest}
|
||||
container_name: wecom_it_admin
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVICE_NAME=admin
|
||||
# 企微凭证
|
||||
- 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}
|
||||
# 数据库
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis
|
||||
- REDIS_URL=redis://redis:6379/0
|
||||
# CORS
|
||||
- CORS_ORIGINS=${CORS_ORIGINS:-http://itsupport.servyou.com.cn}
|
||||
# Mock 登录
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8005
|
||||
volumes:
|
||||
- backend-uploads:/app/uploads
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8005 --workers 1
|
||||
networks:
|
||||
- it-desk-internal
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
reservations:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8005/health').read()"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Nginx — 反向代理 + 静态文件服务 + 路由分发
|
||||
# --------------------------------------------------------------------------
|
||||
nginx:
|
||||
image: nginx:1.27-alpine
|
||||
container_name: wecom_it_nginx
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx-split.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./nginx/ssl:/etc/nginx/ssl:ro
|
||||
- ./frontend-h5/dist:/usr/share/nginx/html/itdesk: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
|
||||
depends_on:
|
||||
core-svc:
|
||||
condition: service_healthy
|
||||
conversation-svc:
|
||||
condition: service_healthy
|
||||
agent-svc:
|
||||
condition: service_healthy
|
||||
ai-svc:
|
||||
condition: service_healthy
|
||||
admin-svc:
|
||||
condition: service_healthy
|
||||
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
|
||||
backend-uploads:
|
||||
name: wecom_it_backend_uploads
|
||||
@@ -24,7 +24,7 @@ services:
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-wecom}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-wecom_secret}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-wecom_secret_2026}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-wecom_it_desk}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
@@ -82,7 +82,7 @@ services:
|
||||
- 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}
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-wecom}:${POSTGRES_PASSWORD:-wecom_secret_2026}@postgres:5432/${POSTGRES_DB:-wecom_it_desk}
|
||||
# Redis(Docker 内部网络,带密码认证)
|
||||
- REDIS_URL=redis://:${REDIS_PASSWORD:-R3d!s@2026#Secure}@redis:6379/0
|
||||
# CORS
|
||||
@@ -97,6 +97,9 @@ services:
|
||||
- DIFY_WINGMAN_TIMEOUT=${DIFY_WINGMAN_TIMEOUT:-30}
|
||||
# Mock 登录(生产环境默认关闭,如需临时调试请在 .env 中显式设置为 true)
|
||||
- MOCK_LOGIN_ENABLED=${MOCK_LOGIN_ENABLED:-false}
|
||||
# 企微 SSO 认证(v0.7.1 新增)
|
||||
- WECOM_SSO_ENABLED=${WECOM_SSO_ENABLED:-false}
|
||||
- WECOM_SSO_CALLBACK_BASE=${WECOM_SSO_CALLBACK_BASE:-https://itsupport.servyou.com.cn}
|
||||
# 服务配置
|
||||
- BACKEND_HOST=0.0.0.0
|
||||
- BACKEND_PORT=8000
|
||||
@@ -139,10 +142,10 @@ services:
|
||||
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-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
|
||||
- ./html/itdesk:/usr/share/nginx/html/itdesk:ro
|
||||
- ./html/itagent:/usr/share/nginx/html/itagent:ro
|
||||
- ./html/itadmin:/usr/share/nginx/html/itadmin:ro
|
||||
- ./html/itportal:/usr/share/nginx/html/itportal:ro
|
||||
depends_on:
|
||||
- backend
|
||||
networks:
|
||||
|
||||
+26
-201
@@ -1,209 +1,34 @@
|
||||
# =============================================================================
|
||||
# 企微智能IT支持服务台 — Nginx 配置(公司内网服务器版 + HTTPS)
|
||||
# =============================================================================
|
||||
# 目标服务器:10.90.5.110
|
||||
# 域名:itsupport.servyou.com.cn
|
||||
#
|
||||
# 路由规则:
|
||||
# HTTP → 自动重定向到 HTTPS
|
||||
# HTTPS → { /itdesk/, /itagent/, /itadmin/, /api/, /ws/ }
|
||||
# =============================================================================
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 日志格式
|
||||
# ------------------------------------------------------------------
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 基础配置
|
||||
# ------------------------------------------------------------------
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
client_max_body_size 50m; # 支持文件上传(企微媒体文件)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Gzip 压缩(前端静态资源)
|
||||
# ------------------------------------------------------------------
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript
|
||||
application/javascript application/xml+rss
|
||||
application/json application/ld+json;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 安全响应头
|
||||
# ------------------------------------------------------------------
|
||||
# 隐藏 nginx 版本号
|
||||
server_tokens off;
|
||||
|
||||
# 基础安全头(应用到所有响应)
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header X-XSS-Protection "0" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;
|
||||
add_header Cross-Origin-Opener-Policy "same-origin" always;
|
||||
|
||||
# API 路径特殊处理(不加 CSP,只加基础安全头)
|
||||
# 前端路径的 CSP 在各前端 index.html 中单独配置
|
||||
|
||||
# =================================================================
|
||||
# 上游服务定义(Docker 内部网络)
|
||||
# =================================================================
|
||||
upstream backend_api {
|
||||
server backend:8000;
|
||||
# 前端静态文件
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTP → HTTPS 重定向
|
||||
# =================================================================
|
||||
server {
|
||||
listen 80;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# 企微域名验证文件(HTTP 也需要,企微验证可能走 HTTP)
|
||||
location /WW_verify_lxWC7WJDjTQuutBE.txt {
|
||||
alias /usr/share/nginx/html/itdesk/WW_verify_lxWC7WJDjTQuutBE.txt;
|
||||
}
|
||||
|
||||
# 其余全部重定向到 HTTPS
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
# API 反向代理到后端
|
||||
location /api/ {
|
||||
proxy_pass http://wecom_it_backend:8000/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# =================================================================
|
||||
# HTTPS 主服务
|
||||
# =================================================================
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
# H5 端点反向代理
|
||||
location /h5/ {
|
||||
proxy_pass http://wecom_it_backend:8000/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# SSL 证书配置
|
||||
# ------------------------------------------------------------------
|
||||
ssl_certificate /etc/nginx/ssl/servyou.com.cn.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/servyou.com.cn.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 安全头
|
||||
# ------------------------------------------------------------------
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 健康检查端点(用于 Docker healthcheck)
|
||||
# ------------------------------------------------------------------
|
||||
location = /itdesk/health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# H5 员工端 — /itdesk/
|
||||
# ------------------------------------------------------------------
|
||||
location /itdesk/ {
|
||||
alias /usr/share/nginx/html/itdesk/;
|
||||
index index.html;
|
||||
try_files $uri /itdesk/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 坐席工作台 — /itagent/
|
||||
# ------------------------------------------------------------------
|
||||
location /itagent/ {
|
||||
alias /usr/share/nginx/html/itagent/;
|
||||
index index.html;
|
||||
try_files $uri /itagent/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 统一入口 Portal — /itportal/
|
||||
# ------------------------------------------------------------------
|
||||
location /itportal/ {
|
||||
alias /usr/share/nginx/html/itportal/;
|
||||
index index.html;
|
||||
try_files $uri /itportal/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 管理后台 — /itadmin/
|
||||
# ------------------------------------------------------------------
|
||||
location /itadmin/ {
|
||||
alias /usr/share/nginx/html/itadmin/;
|
||||
index index.html;
|
||||
try_files $uri /itadmin/index.html;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 后端 API — /api/
|
||||
# ------------------------------------------------------------------
|
||||
location /api/ {
|
||||
proxy_pass http://backend_api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
|
||||
# 超时设置(AI 回复可能较慢)
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# WebSocket — /ws/(坐席端实时通信)
|
||||
# ------------------------------------------------------------------
|
||||
location /ws/ {
|
||||
access_log off; # P0-#4: 关闭 WS 路径日志,避免 token 泄露
|
||||
proxy_pass http://backend_api;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_read_timeout 86400s; # WebSocket 长连接
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 企微域名验证文件
|
||||
# ------------------------------------------------------------------
|
||||
location /WW_verify_lxWC7WJDjTQuutBE.txt {
|
||||
alias /usr/share/nginx/html/itdesk/WW_verify_lxWC7WJDjTQuutBE.txt;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 默认路径 — 重定向到统一入口 Portal
|
||||
# ------------------------------------------------------------------
|
||||
location = / {
|
||||
return 302 /itportal/;
|
||||
}
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
# =============================================================================
|
||||
# 企微IT智能服务台 — Nginx 配置(多服务拆分版)
|
||||
# =============================================================================
|
||||
# 路由策略:
|
||||
# - /api/core/* → core-svc:8001
|
||||
# - /api/conversations/*, /api/messages/*, /api/h5/*, /ws/* → conversation-svc:8002
|
||||
# - /api/agents/* → agent-svc:8003
|
||||
# - /api/ai/* → ai-svc:8004
|
||||
# - /api/admin/* → admin-svc:8005
|
||||
# - /*.html, /itdesk/*, /itagent/*, /itadmin/*, /itportal/* → 静态文件
|
||||
# =============================================================================
|
||||
|
||||
worker_processes auto;
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
use epoll;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
# 日志格式
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
# 性能优化
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
types_hash_max_size 2048;
|
||||
client_max_body_size 50m;
|
||||
|
||||
# Gzip 压缩
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml;
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 上游服务定义(拆分版)
|
||||
# ----------------------------------------------------------------------
|
||||
upstream core_backend {
|
||||
server core-svc:8001 max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream conversation_backend {
|
||||
server conversation-svc:8002 max_fails=3 fail_timeout=30s;
|
||||
keepalive 64;
|
||||
}
|
||||
|
||||
upstream agent_backend {
|
||||
server agent-svc:8003 max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream ai_backend {
|
||||
server ai-svc:8004 max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
upstream admin_backend {
|
||||
server admin-svc:8005 max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# 静态文件服务(H5用户端)
|
||||
# ----------------------------------------------------------------------
|
||||
server {
|
||||
listen 80;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# HTTP → HTTPS 跳转
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name itsupport.servyou.com.cn;
|
||||
|
||||
# SSL 证书
|
||||
ssl_certificate /etc/nginx/ssl/servyou.com.cn.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/servyou.com.cn.key;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_tickets off;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
|
||||
ssl_prefer_server_ciphers off;
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 健康检查端点(不经过代理)
|
||||
# ------------------------------------------------------------------
|
||||
location = /itdesk/health {
|
||||
access_log off;
|
||||
return 200 "OK";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# API 路由分发(根据路径选择上游服务)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# Core 服务:认证、员工、角色
|
||||
location ~ ^/api/(auth|employees|roles|mfa) {
|
||||
proxy_pass http://core_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering off;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
|
||||
# AI 服务:Dify 调用、Wingman
|
||||
location ~ ^/api/(ai|wingman|dify) {
|
||||
proxy_pass http://ai_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 90s; # AI 响应可能较慢
|
||||
proxy_buffering off;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
|
||||
# Admin 服务:管理后台 API
|
||||
location ~ ^/api/admin {
|
||||
proxy_pass http://admin_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering off;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
|
||||
# Agent 服务:坐席 API
|
||||
location ~ ^/api/agents {
|
||||
proxy_pass http://agent_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering off;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
|
||||
# Conversation 服务:会话、消息、H5 API
|
||||
location ~ ^/api/(conversations|messages|h5|quick-replies) {
|
||||
proxy_pass http://conversation_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering off;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
|
||||
# WebSocket 服务(会话服务)
|
||||
location /ws/ {
|
||||
proxy_pass http://conversation_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 7d;
|
||||
proxy_send_timeout 7d;
|
||||
proxy_read_timeout 7d;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
# 通用 API 路由(兜底)
|
||||
location /api/ {
|
||||
proxy_pass http://conversation_backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 30s;
|
||||
proxy_send_timeout 30s;
|
||||
proxy_read_timeout 30s;
|
||||
proxy_buffering off;
|
||||
proxy_set_header Connection "";
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 静态文件服务
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# H5 用户端
|
||||
location /itdesk/ {
|
||||
alias /usr/share/nginx/html/itdesk/;
|
||||
try_files $uri $uri/ /itdesk/index.html;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
}
|
||||
|
||||
# 坐席端
|
||||
location /itagent/ {
|
||||
alias /usr/share/nginx/html/itagent/;
|
||||
try_files $uri $uri/ /itagent/index.html;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
}
|
||||
|
||||
# 管理后台
|
||||
location /itadmin/ {
|
||||
alias /usr/share/nginx/html/itadmin/;
|
||||
try_files $uri $uri/ /itadmin/index.html;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
}
|
||||
|
||||
# Portal 入口
|
||||
location /itportal/ {
|
||||
alias /usr/share/nginx/html/itportal/;
|
||||
try_files $uri $uri/ /itportal/index.html;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
}
|
||||
|
||||
# 根路径重定向到 Portal
|
||||
location = / {
|
||||
return 302 /itportal/;
|
||||
}
|
||||
|
||||
# 默认处理
|
||||
location / {
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,6 +206,7 @@ http {
|
||||
|
||||
# 其他 API 路径
|
||||
proxy_pass http://backend_api/;
|
||||
proxy_redirect off; # 禁用重定向修改,让后端的 307/302 保持原始 location
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
Reference in New Issue
Block a user