Files

263 lines
8.8 KiB
Markdown
Raw Permalink 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.
# 生产环境部署文档
## 概览
| 项目 | 内容 |
|------|------|
| 域名 | `https://trade.yuzhiran.com` |
| 备案号 | 京ICP备2026007249号-1 |
| 公安备案 | 京公网安备11011502039545号 |
| 服务器 | 阿里云(Alibaba Cloud Linux 3 |
| Web 服务器 | Nginx(宝塔面板管理) |
| 后端 | FastAPI + uvicornPython 3.11, 2 workers |
| 前端 | uni-app Vue 3H5 构建产物) |
| 数据库 | PostgreSQL 13, 数据库 `foreign_trade` |
| 用户 | `www`(宝塔默认用户) |
## 目录结构
```
/www/wwwroot/trade.yuzhiran.com/
├── backend/ # FastAPI 后端
│ ├── .env # 生产环境变量
│ ├── venv/ # Python 3.11 虚拟环境
│ ├── app/ # 应用代码
│ ├── alembic/ # 数据库迁移
│ ├── alembic.ini # Alembic 配置(已改为从 .env 读取 URL)
│ └── requirements.txt
├── uni-app/ # 前端源码(保留用)
│ ├── src/
│ └── dist/build/h5/ # H5 构建产物
├── deploy/ # 部署配置模板
│ ├── README.md
│ ├── backend/
│ │ ├── .env.production
│ │ └── supervisord.conf
│ ├── frontend/
│ │ └── nginx.conf
│ └── database/
│ └── migrate.sh
├── assets/ # 前端静态资源
├── static/ # 前端静态资源
└── index.html # SPA 入口
# 日志
/www/wwwlogs/
├── trademate-backend.log # uvicorn 后端日志
├── trademate-backend.error.log
└── trade.yuzhiran.com.log # Nginx 访问日志
```
## 部署步骤
### 1. 创建 PostgreSQL 用户和授权
```bash
# 数据库 foreign_trade 已存在,需创建用户并授权
PGPASSWORD=your_password psql -U postgres -h localhost -c "CREATE ROLE foreign_trade WITH LOGIN PASSWORD 'your_password';"
PGPASSWORD=your_password psql -U postgres -h localhost -c "GRANT ALL PRIVILEGES ON DATABASE foreign_trade TO foreign_trade;"
PGPASSWORD=your_password psql -U postgres -h localhost -d foreign_trade -c "GRANT ALL ON SCHEMA public TO foreign_trade;"
PGPASSWORD=your_password psql -U postgres -h localhost -d foreign_trade -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO foreign_trade;"
PGPASSWORD=your_password psql -U postgres -h localhost -d foreign_trade -c "ALTER SCHEMA public OWNER TO foreign_trade;"
```
### 2. 部署代码到站点目录
```bash
# 将 production 分支代码复制到站点目录
cd /root/hermes-workspace/projects/trade-assistant
tar --exclude='.git' --exclude='node_modules' --exclude='__pycache__' \
--exclude='*.pyc' --exclude='.pytest_cache' --exclude='venv' \
--exclude='.coverage' --exclude='.env' \
-cf - . | tar -xf - -C /www/wwwroot/trade.yuzhiran.com/
```
### 3. 配置后端环境变量
```bash
cp deploy/backend/.env.production backend/.env
# 编辑 backend/.env 填入:
# - SECRET_KEY(随机字符串, 用 python3 -c "import secrets; print(secrets.token_urlsafe(48))" 生成)
# - AI API KeyOPENAI_API_KEY / SENSENOVA_API_KEY 等)
```
### 4. 安装 Python 3.11 和依赖
```bash
yum install -y python3.11
cd /www/wwwroot/trade.yuzhiran.com/backend
python3.11 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install python-dotenv 'pydantic[dotenv]'
```
### 5. 配置 Alembic(重要!)
```bash
# 编辑 backend/alembic/env.py,在第15行后加入:
from app.config import settings
config.set_main_option("sqlalchemy.url", settings.DATABASE_URL)
# 这样 alembic 会从 .env 读取 DATABASE_URL,而非硬编码
```
### 6. 运行数据库迁移
```bash
cd /www/wwwroot/trade.yuzhiran.com/backend
source venv/bin/activate
alembic upgrade head
```
预期输出:
```
Running upgrade -> 001, initial schema
Running upgrade 001 -> 002, add teams and analytics tables
Running upgrade 002 -> 003, add notifications, feedback, subscription, and p3 tables
Running upgrade 003 -> 004, add devices table for push notification registration
Running upgrade 004 -> 005, add followup_strategies and followup_logs tables
```
### 7. 构建前端
```bash
cd /www/wwwroot/trade.yuzhiran.com/uni-app
npm install
npm run build:h5
# 复制构建产物到站点根目录
cp -r dist/build/h5/* /www/wwwroot/trade.yuzhiran.com/
```
### 8. 配置 Nginx(宝塔面板操作)
在宝塔面板 → 网站 → 设置 → 配置文件 中替换为以下配置,或直接修改文件 `/www/server/panel/vhost/nginx/trade.yuzhiran.com.conf`
核心要点:
- 保留 CERT-APPLY-CHECK 和 .well-known 配置(宝塔 SSL 证书验证需要)
- 保留敏感文件/目录防护(宝塔自动生成)
- 添加 `location /api/` 代理到 `127.0.0.1:8000`
- 添加 `location /` 的 SPA fallback: `try_files $uri $uri/ /index.html`
- 删除 `enable-php-00.conf` 引用(本项目无需 PHP
Nginx 完整配置见 `deploy/frontend/nginx.conf`
### 9. 启动后端
```bash
# 设置权限
chown -R www:www /www/wwwroot/trade.yuzhiran.com/backend
# 切换 www 用户启动
sudo -u www nohup /www/wwwroot/trade.yuzhiran.com/backend/venv/bin/uvicorn \
app.main:app --host 127.0.0.1 --port 8000 --workers 2 \
>> /www/wwwlogs/trademate-backend.log 2>&1 &
```
**注意**: `www` 用户默认 shell 为 `/sbin/nologin`,无法通过 `su - www` 登录。必须使用 `sudo -u www``runuser`
### 10. 申请 SSL 证书(宝塔面板操作)
1. 宝塔面板 → 网站 → trade.yuzhiran.com → SSL
2. 选择 Let's Encrypt → 文件验证
3. 申请成功后自动配置 HTTPS 重定向
### 11. 验证
```bash
curl -s http://127.0.0.1:8000/health # -> {"status":"ok"}
curl -s -H "Host: trade.yuzhiran.com" http://127.0.0.1/ # -> HTML 页面
curl -s https://trade.yuzhiran.com/api/v1/admin/health # -> admin 健康检查
```
## 宝塔面板兼容说明
### 文件验证与 SSL
宝塔申请 SSL 证书时使用文件验证方式,会在 `.well-known` 目录放置验证文件。Nginx 配置必须保留:
```nginx
#CERT-APPLY-CHECK--START
include /www/server/panel/vhost/nginx/well-known/trade.yuzhiran.com.conf;
#CERT-APPLY-CHECK--END
location ~ \.well-known {
allow all;
}
```
这两个配置块缺一不可,否则宝塔面板会报 "配置文件被修改不支持文件验证"。
### www 用户部署
宝塔面板以 `www` 用户运行,所有站点文件必须属于 `www:www`
```bash
chown -R www:www /www/wwwroot/trade.yuzhiran.com/
```
`www` 用户特点:
- shell 为 `/sbin/nologin`,不能交互登录
- 启动后台进程需要 `sudo -u www``runuser`
- 文件权限必须正确,否则 Nginx 无法读取静态文件
### 宝塔面板可操作内容
| 操作 | 面板操作 | 说明 |
|------|---------|------|
| SSL 证书申请 | ✅ | 文件验证,配置保留即可 |
| Nginx 配置修改 | ✅ | 可通过面板修改,注意保留 API 代理和 SPA fallback |
| 数据库管理 | ✅ | phpMyAdmin / 面板 phpPgAdmin |
| 文件管理 | ✅ | 可查看/编辑站点文件 |
| 进程管理 | ❌ | 后端 uvicorn 需命令行管理,面板 Python 项目管理器暂未配置 |
### 推荐的生产维护方式
```
# 重启后端
kill -9 $(pgrep -f "uvicorn app.main" | head -1)
sudo -u www nohup /www/wwwroot/trade.yuzhiran.com/backend/venv/bin/uvicorn \
app.main:app --host 127.0.0.1 --port 8000 --workers 2 \
>> /www/wwwlogs/trademate-backend.log 2>&1 &
# 查看后端日志
tail -f /www/wwwlogs/trademate-backend.log
# 重新构建前端
cd /www/wwwroot/trade.yuzhiran.com/uni-app && npm run build:h5
cp -r dist/build/h5/* /www/wwwroot/trade.yuzhiran.com/
# 数据库迁移
cd /www/wwwroot/trade.yuzhiran.com/backend && source venv/bin/activate && alembic upgrade head
```
## 关键配置
### 环境变量(backend/.env
```
DATABASE_URL=postgresql+asyncpg://foreign_trade:password@localhost:5432/foreign_trade
FRONTEND_URL=https://trade.yuzhiran.com
BACKEND_URL=https://trade.yuzhiran.com
DEBUG=false
DB_ECHO=false
```
### Alembicbackend/alembic.ini
生产环境不再硬编码数据库 URL,改为从 `.env` 读取。`alembic/env.py` 中通过 `config.set_main_option("sqlalchemy.url", settings.DATABASE_URL)` 动态设置。
## 常见问题
### Q: 前端页面空白 / 路由 404
重新加载页面(SPA fallback),确认 Nginx 配置有 `try_files $uri $uri/ /index.html`
### Q: API 请求 500,日志显示 "invalid UUID"
路由顺序问题 —— 参数化路由(如 `/{customer_id}`)必须在具名路由(如 `/health-scores`)之后定义。参照 `customer.py` 的修正。
### Q: 宝塔面板申请 SSL 失败
检查 Nginx 配置中是否保留了 `#CERT-APPLY-CHECK` 注释块和 `.well-known` location。
### Q: 后端启动后马上退出
检查端口 8000 是否被占用:`lsof -i :8000`。检查日志:`tail -f /www/wwwlogs/trademate-backend.log`