356 lines
11 KiB
Markdown
356 lines
11 KiB
Markdown
# shanxia2.0 生产环境部署方案
|
||
|
||
> 目标机器:`121.43.228.102`
|
||
> 与现有 CRM(80 端口 / `web.conf`)**并存**,通过 **9911(前端)+ 9111(后端)** 独立端口部署山峡一体化门户。
|
||
|
||
---
|
||
|
||
## 1. 部署思路总览
|
||
|
||
### 1.1 架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ 121.43.228.102 │
|
||
│ │
|
||
浏览器 ──────────►│ nginx :9911 │
|
||
(管理端) │ ├─ / → 静态 dist (SPA) │
|
||
│ └─ /api/* → 127.0.0.1:9111 │
|
||
│ │
|
||
│ uvicorn :9111 (FastAPI) │
|
||
│ ├─ MySQL 47.99.164.66:3306 │
|
||
│ ├─ Redis 47.99.164.66:16379 │
|
||
│ └─ MinIO 47.99.164.66:20004 │
|
||
│ │
|
||
浏览器 ──────────►│ nginx :80 (现有 CRM,保持不变) │
|
||
(CRM) │ └─ /prod-api/* → :8080 │
|
||
└─────────────────────────────────────────┘
|
||
```
|
||
|
||
### 1.2 核心原则
|
||
|
||
| 项 | 说明 |
|
||
|---|---|
|
||
| **端口隔离** | CRM 继续占用 80;shanxia2.0 使用 9911/9111,互不影响 |
|
||
| **同库同中间件** | 数据库、Redis、MinIO 与本地开发一致(远程 `47.99.164.66`) |
|
||
| **Nginx 反代 API** | 前端 `VITE_API_URL=/api`,由 Nginx 转发到后端,避免浏览器跨域 |
|
||
| **后端仅本机监听** | 9111 建议只绑定 `127.0.0.1`,对外只暴露 9911 |
|
||
| **环境文件分离** | 生产使用 `backend/.env.production`,不直接使用开发 `.env` |
|
||
| **构建在本地/CI** | 服务器只放 `dist` 与 Python 源码,不在生产机跑 `pnpm dev` |
|
||
|
||
### 1.3 目录约定(生产机)
|
||
|
||
| 路径 | 内容 |
|
||
|---|---|
|
||
| `/iflytek/shanxia2.0/backend` | Python 后端源码 + venv + `.env.production` |
|
||
| `/iflytek/shanxia2.0/web/dist` | 前端 `pnpm build` 产物(仓库对应 `web-admin/dist`) |
|
||
| `/etc/nginx/conf.d/shanxia2.0.conf` | Nginx 站点配置(见同目录模板) |
|
||
|
||
> 仓库前端工程名为 `web-admin`,部署到服务器时目录按约定命名为 `web/dist`。
|
||
|
||
---
|
||
|
||
## 2. 前置条件
|
||
|
||
### 2.1 服务器软件
|
||
|
||
- **Python 3.9+**(与本地 venv 一致;需 `python3-venv`)
|
||
- **Nginx**(已有,用于 CRM)
|
||
- **Node.js 20.19+ / pnpm 8.8+**(仅在构建机构建,生产机可选)
|
||
|
||
### 2.2 网络与防火墙
|
||
|
||
- 安全组/防火墙放行 **9911/TCP**(对外 Web 访问)
|
||
- **9111** 建议不对公网开放(仅 Nginx 本机反代)
|
||
- 确认生产机可访问 `47.99.164.66:3306 / 16379 / 20004`
|
||
|
||
### 2.3 数据库
|
||
|
||
- 库名:`shanxia2.0`(与本地 `DATABASE_URL` 一致)
|
||
- 基线 DDL:`docs/sql/shanxia2.0.sql`
|
||
- 增量脚本:按日期顺序执行 `docs/sql/2026*.sql` 等迁移文件
|
||
- 可选表:`docs/sql/optional-sys-api-request-log.sql`(不建表则设置 `API_REQUEST_LOG_ENABLED=false`)
|
||
|
||
---
|
||
|
||
## 3. 部署步骤
|
||
|
||
### 阶段 A:准备代码(本地或 CI)
|
||
|
||
#### A1. 检出/打包后端
|
||
|
||
```bash
|
||
# 本地打包示例(排除 venv、日志、缓存)
|
||
cd /path/to/shanxia2.0
|
||
tar czf shanxia2.0-backend.tar.gz \
|
||
--exclude='backend/venv' \
|
||
--exclude='backend/logs' \
|
||
--exclude='backend/__pycache__' \
|
||
--exclude='backend/.env' \
|
||
backend/
|
||
```
|
||
|
||
#### A2. 配置生产环境变量
|
||
|
||
1. 复制 `生产环境部署/backend.env.production.example` → 服务器 `backend/.env.production`
|
||
2. 以本地 `backend/.env` 中的 **DATABASE / Redis / MinIO** 值为基准填入
|
||
3. **必须修改**的生产项:
|
||
- `DEBUG=false`
|
||
- `SECRET_KEY` → 随机长字符串(勿用默认值)
|
||
- `LOGIN_RSA_PRIVATE_KEY_PEM` → 固定 PEM(多 worker / 重启后登录公钥不变)
|
||
- `BACKEND_CORS_ORIGINS=["http://121.43.228.102:9911"]`(若后续绑域名一并加入)
|
||
- `PUBLIC_WEB_ORIGIN=http://121.43.228.102:9911`(公开 H5 页链接)
|
||
|
||
#### A3. 构建前端
|
||
|
||
1. 复制 `生产环境部署/web-admin.env.production.example` → `web-admin/.env.production`
|
||
2. 构建:
|
||
|
||
```bash
|
||
cd web-admin
|
||
pnpm install
|
||
pnpm build
|
||
# 产物:web-admin/dist/
|
||
```
|
||
|
||
3. 打包 dist:
|
||
|
||
```bash
|
||
tar czf shanxia2.0-web-dist.tar.gz -C web-admin dist
|
||
```
|
||
|
||
---
|
||
|
||
### 阶段 B:上传到生产机
|
||
|
||
```bash
|
||
# 在本地执行(示例)
|
||
scp shanxia2.0-backend.tar.gz root@121.43.228.102:/iflytek/shanxia2.0/
|
||
scp shanxia2.0-web-dist.tar.gz root@121.43.228.102:/iflytek/shanxia2.0/
|
||
scp 生产环境部署/nginx-shanxia2.0.conf root@121.43.228.102:/etc/nginx/conf.d/
|
||
```
|
||
|
||
在服务器解压:
|
||
|
||
```bash
|
||
mkdir -p /iflytek/shanxia2.0/backend /iflytek/shanxia2.0/web
|
||
cd /iflytek/shanxia2.0
|
||
tar xzf shanxia2.0-backend.tar.gz
|
||
mkdir -p web && tar xzf shanxia2.0-web-dist.tar.gz -C web
|
||
# 解压后路径应为 /iflytek/shanxia2.0/web/dist/index.html
|
||
```
|
||
|
||
---
|
||
|
||
### 阶段 C:后端初始化与启动
|
||
|
||
```bash
|
||
cd /iflytek/shanxia2.0/backend
|
||
|
||
# 创建虚拟环境并安装依赖
|
||
python3 -m venv venv
|
||
./venv/bin/pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||
|
||
# 确认环境文件
|
||
ls -la .env.production
|
||
|
||
# 启动(端口 9111,2 worker)
|
||
PORT=9111 WORKERS=2 ENV_FILE=./.env.production ./start-prod.sh start
|
||
|
||
# 查看状态与日志
|
||
./start-prod.sh status
|
||
./start-prod.sh logs
|
||
```
|
||
|
||
健康检查(服务器本机):
|
||
|
||
```bash
|
||
curl -s http://127.0.0.1:9111/health
|
||
# 期望:{"status":"healthy"}
|
||
```
|
||
|
||
---
|
||
|
||
### 阶段 D:Nginx 配置
|
||
|
||
1. 使用本目录 `nginx-shanxia2.0.conf`(已按 9911 / 9111 写好)
|
||
2. 检查并重载:
|
||
|
||
```bash
|
||
nginx -t
|
||
nginx -s reload
|
||
# 或 systemctl reload nginx
|
||
```
|
||
|
||
3. 验证:
|
||
|
||
```bash
|
||
curl -s http://127.0.0.1:9911/health
|
||
curl -s http://127.0.0.1:9911/api/... # 任选一个公开接口
|
||
curl -I http://127.0.0.1:9911/
|
||
```
|
||
|
||
---
|
||
|
||
### 阶段 E:业务验收
|
||
|
||
| 检查项 | 操作 | 期望 |
|
||
|---|---|---|
|
||
| 静态页 | 浏览器打开 `http://121.43.228.102:9911` | 登录页正常 |
|
||
| 登录 | admin / 111111(或实际账号) | RSA 登录成功,进入工作台 |
|
||
| API 代理 | F12 Network 看请求 | 均为同源 `/api/...`,无 CORS 报错 |
|
||
| 附件 | 上传/预览 | MinIO URL 可访问 |
|
||
| 路由 | 刷新任意 `#/pl/...` 页面 | 不出现 404(SPA fallback) |
|
||
| CRM 不受影响 | 访问 `http://121.43.228.102` | CRM 仍正常 |
|
||
|
||
---
|
||
|
||
## 4. 与 CRM Nginx 配置的对比
|
||
|
||
| 对比项 | CRM (`web.conf`) | shanxia2.0 (`shanxia2.0.conf`) |
|
||
|---|---|---|
|
||
| 监听端口 | 80 | **9911** |
|
||
| 静态根目录 | `/iflytek/prod/dist` | `/iflytek/shanxia2.0/web/dist` |
|
||
| API 前缀 | `/prod-api/` | **`/api/`** |
|
||
| 后端端口 | 8080 (Java) | **9111** (Python) |
|
||
| SSE | 有专用 location | 当前门户暂无 SSE,可后续按需追加 |
|
||
|
||
shanxia2.0 的 Nginx 写法**参照 CRM 的代理头、超时、Gzip、SPA fallback**,仅替换端口与路径前缀。
|
||
|
||
---
|
||
|
||
## 5. 环境变量要点
|
||
|
||
### 5.1 后端(`.env.production`)
|
||
|
||
详见 `backend.env.production.example`。与本地 `.env` 对齐的字段:
|
||
|
||
- `DATABASE_URL`
|
||
- `REDIS_*`
|
||
- `MINIO_*` / `STORAGE_TYPE=minio`
|
||
- `DEFAULT_TENANT_NO=shanxia2.0`
|
||
- `API_ENCRYPT_*`(当前本地为 `false`,生产保持一致即可;若开启需前后端同时开启且密钥一致)
|
||
|
||
生产**额外**注意:
|
||
|
||
- `DEBUG=false`
|
||
- `LOGIN_ALLOW_PLAINTEXT_LOGIN=false`
|
||
- 配置固定 `LOGIN_RSA_PRIVATE_KEY_PEM`(可从本地生成后复制,或使用 `openssl genrsa 2048`)
|
||
|
||
### 5.2 前端(`.env.production`,构建时生效)
|
||
|
||
详见 `web-admin.env.production.example`:
|
||
|
||
- `VITE_API_URL=/api`(走 Nginx 同源代理)
|
||
- `VITE_BASE_URL=/`
|
||
- `VITE_API_ENCRYPT_ENABLED=false`(与后端一致)
|
||
- `VITE_MINIO_BASE_URL=https://res.shanxiachem.com/ruoyi`(与后端 `MINIO_BASE_URL` 一致)
|
||
|
||
---
|
||
|
||
## 6. 日常运维
|
||
|
||
### 6.0 一键发版(推荐)
|
||
|
||
macOS 本机从仓库根目录执行(凭据读自根目录 `生产机器账号密码`,密码不写进脚本):
|
||
|
||
```bash
|
||
./生产环境部署/deploy-release.sh
|
||
# 已有 dist 时可跳过构建:
|
||
./生产环境部署/deploy-release.sh --skip-build
|
||
```
|
||
|
||
顺序:本地 `pnpm build` → 备份远程 `web` → 同步 `dist`(**保留**远程 `dist/src`)→ 备份远程 `backend` → 替换 `backend/app` → `PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart` → 健康检查。
|
||
|
||
备份落在 `/iflytek/shanxia2.0/bak/web-*` 与 `backend-*`。依赖:`ssh`、`rsync`、`sshpass`(`brew install hudochenkov/sshpass/sshpass`)、`pnpm`。
|
||
|
||
### 6.1 更新后端(手工)
|
||
|
||
```bash
|
||
cd /iflytek/shanxia2.0/backend
|
||
# 上传新代码后
|
||
./venv/bin/pip install -r requirements.txt
|
||
PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart
|
||
```
|
||
|
||
### 6.2 更新前端(手工)
|
||
|
||
```bash
|
||
# 本地 build 后上传 dist;务必保留远程 dist/src
|
||
rsync -avz --delete --exclude 'src/' web-admin/dist/ root@121.43.228.102:/iflytek/shanxia2.0/web/dist/
|
||
# 无需重启后端;浏览器强刷或清缓存
|
||
```
|
||
|
||
### 6.3 数据库变更
|
||
|
||
1. 在 `docs/sql/` 编写增量 SQL
|
||
2. 在生产库按顺序执行
|
||
3. 再发版后端/前端
|
||
|
||
### 6.4 日志位置
|
||
|
||
| 组件 | 路径 |
|
||
|---|---|
|
||
| 后端 | `/iflytek/shanxia2.0/backend/logs/backend-prod.log` |
|
||
| Nginx | 按现有 CRM 同样 log 目录配置(可在 conf 中取消注释) |
|
||
|
||
### 6.5 开机自启(可选)
|
||
|
||
可使用 systemd unit 管理 `start-prod.sh`:
|
||
|
||
```ini
|
||
# /etc/systemd/system/shanxia2.0-backend.service
|
||
[Unit]
|
||
Description=shanxia2.0 FastAPI Backend
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=forking
|
||
WorkingDirectory=/iflytek/shanxia2.0/backend
|
||
Environment=PORT=9111
|
||
Environment=WORKERS=2
|
||
Environment=ENV_FILE=/iflytek/shanxia2.0/backend/.env.production
|
||
ExecStart=/iflytek/shanxia2.0/backend/start-prod.sh start
|
||
ExecStop=/iflytek/shanxia2.0/backend/start-prod.sh stop
|
||
Restart=on-failure
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl enable shanxia2.0-backend
|
||
systemctl start shanxia2.0-backend
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 回滚策略
|
||
|
||
1. **前端**:`/iflytek/shanxia2.0/bak/web-*` 中对应备份覆盖回 `web`(注意勿误删业务依赖的 `dist/src`)
|
||
2. **后端**:从 `bak/backend-*` 还原后,在 `backend` 目录执行 `PORT=9111 WORKERS=1 ENV_FILE=./.env.production ./start-prod.sh restart`
|
||
3. **数据库**:增量 SQL 应可逆或先备份;重大变更前 `mysqldump`
|
||
|
||
---
|
||
|
||
## 8. 后续可选增强
|
||
|
||
- **域名 + HTTPS**:为 9911 配置 `portal.shanxiachem.com` + SSL,并更新 `BACKEND_CORS_ORIGINS`
|
||
- **API 加密**:生产开启 `API_ENCRYPT_ENABLED=true`,前后端密钥与排除路径保持一致
|
||
- **独立 API 域名**:小程序/外部系统可配置 `http://121.43.228.102:9911/api` 或单独域名
|
||
- **监控**:对 `/health` 做存活探测;对接现有 Spring Boot Admin 以外的监控
|
||
|
||
---
|
||
|
||
## 9. 文件清单
|
||
|
||
| 文件 | 用途 |
|
||
|---|---|
|
||
| `README.md` | 本文档 |
|
||
| `deploy-release.sh` | macOS 一键发版(前端→后端,含备份与健康检查) |
|
||
| `nginx-shanxia2.0.conf` | Nginx 站点模板 |
|
||
| `backend.env.production.example` | 后端生产环境变量模板 |
|
||
| `web-admin.env.production.example` | 前端构建环境变量模板 |
|
||
| `deploy-checklist.md` | 上线检查清单(可打印) |
|