jiachenlong/docs/DEPLOYMENT.md

637 lines
14 KiB
Markdown
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.

# 甲辰藏品管理系统 部署手册
**当前版本v1.2.88**
---
## 环境概览
### 服务器信息
| 环境 | 前端 | 后端 | SSH密码 |
|------|------|------|--------|
| **D测试环境** | 114.55.137.168, 172.26.30.32 (内网) | 47.111.184.210, 172.26.30.33 (内网) | Jiachend123 |
| **101生产环境** | 47.98.171.101 (80端口) | 47.98.171.101:8080 | Coolbot123 |
### 数据库信息
| 用途 | 数据库 | 地址 | 端口 | 用户名 | 密码 |
|------|--------|------|------|--------|------|
| **主数据库** | jiachenlong | pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com | 5432 | jiachenlong | Passwd1@3 |
| **一尘数据库** | coolbot_data | pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com | 5432 | coolbot | Coolbot123 |
> ⚠️ **密码中的特殊字符 `@` 必须URL编码为 `%40`**
> - `Passwd1@3` → `Passwd1%403`
> - `Coolbot123` 无需编码
### OSS存储
- Bucket: jiachenlong-oss
---
## 环境变量 (.env)
> 📁 完整示例见 `backend/.env.example`
### 数据库配置
```env
# 主数据库 - jiachenlong
DATABASE_URL=postgresql://jiachenlong:Passwd1%403@pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com:5432/jiachenlong
# 一尘数据库 - coolbot_data
COOLBOT_DB_URL=postgresql://coolbot:Coolbot123@pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com:5432/coolbot_data
```
### JWT认证配置
```env
SECRET_KEY=jiachenlong-production-secret-key-2026
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=10080
```
### 阿里云百炼AI (DASHSCOPE)
```env
# 用于AI批量解析藏品行情数据
DASHSCOPE_API_KEY=your-dashscope-api-key
```
### 阿里云OSS存储
```env
OSS_ACCESS_KEY_ID=your-oss-access-key-id
OSS_ACCESS_KEY_SECRET=your-oss-access-key-secret
OSS_BUCKET=jiachenlong-oss
OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
```
### 阿里云短信服务
```env
SMS_ACCESS_KEY_ID=your-sms-access-key-id
SMS_ACCESS_KEY_SECRET=your-sms-access-key-secret
SMS_SIGN_NAME=您的签名
SMS_TEMPLATE_CODE=SMS_xxx
```
### 请求限流配置
```env
RATE_LIMIT_ENABLED=true
RATE_LIMIT_SMS_PER_MINUTE=3
RATE_LIMIT_OCR_PER_MINUTE=10
RATE_LIMIT_BATCH_PER_MINUTE=5
RATE_LIMIT_API_PER_MINUTE=60
```
### 管理员账号
```env
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
```
---
## 部署流程
### 1. 获取代码
```bash
# 克隆仓库
git clone http://caibotd:Caibotd123@101.37.160.219/root/jiachenlong.git
# 切换到目标版本
cd jiachenlong
git checkout v1.2.88 # 或指定版本tag
```
### 2. 构建前端
```bash
cd frontend
npm install
npm run build
```
### 3. 配置后端环境变量
在后端服务器创建 `.env` 文件:
```bash
cat > /root/jiachenlong/backend/.env << 'EOF'
# 主数据库 - jiachenlong
DATABASE_URL=postgresql://jiachenlong:Passwd1%403@pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com:5432/jiachenlong
# 一尘数据库 - coolbot_data
COOLBOT_DB_URL=postgresql://coolbot:Coolbot123@pgm-bp1t1008h019ez6c.pg.rds.aliyuncs.com:5432/coolbot_data
# JWT
SECRET_KEY=jiachenlong-production-secret-key-2026
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=10080
# 阿里云百炼AI
DASHSCOPE_API_KEY=your-dashscope-api-key
# 阿里云OSS
OSS_ACCESS_KEY_ID=your-oss-access-key-id
OSS_ACCESS_KEY_SECRET=your-oss-access-key-secret
OSS_BUCKET=jiachenlong-oss
OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
# 阿里云SMS
SMS_ACCESS_KEY_ID=your-sms-access-key-id
SMS_ACCESS_KEY_SECRET=your-sms-access-key-secret
SMS_SIGN_NAME=您的签名
SMS_TEMPLATE_CODE=SMS_xxx
# 限流
RATE_LIMIT_ENABLED=true
RATE_LIMIT_SMS_PER_MINUTE=3
RATE_LIMIT_OCR_PER_MINUTE=10
RATE_LIMIT_BATCH_PER_MINUTE=5
RATE_LIMIT_API_PER_MINUTE=60
# 管理员
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
EOF
```
### 4. 上传文件到服务器
```bash
# 上传前端
scp -r frontend/dist/* root@47.111.184.210:/var/www/html/
# 上传后端
scp -r backend/app root@47.111.184.210:/root/jiachenlong/backend/
scp backend/requirements.txt root@47.111.184.210:/root/jiachenlong/backend/
scp backend/.env root@47.111.184.210:/root/jiachenlong/backend/
```
### 5. 配置Nginx
D测试环境配置示例 (`/etc/nginx/nginx.conf`)
```nginx
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
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;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# 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;
server {
listen 80;
server_name _;
# 前端静态文件
root /var/www/html;
index index.html;
# 大文件上传限制
client_max_body_size 50M;
client_body_timeout 300s;
# 前端静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 前端 SPA 路由
location / {
try_files $uri $uri/ /index.html;
}
# API代理到后端
location /api/ {
proxy_pass http://127.0.0.1:3000;
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_read_timeout 300s;
proxy_connect_timeout 75s;
}
# 上传文件代理
location /uploads/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 静态文件服务
location /static/ {
alias /var/www/html/static/;
expires 30d;
}
}
}
```
### 6. 启动后端服务
```bash
# 激活conda环境
source /opt/conda/etc/profile.d/conda.sh
conda activate py312
# 安装依赖(如需要)
pip install -r requirements.txt
# 创建日志目录
mkdir -p /root/jiachenlong/backend/logs
# 设置Python路径
export PYTHONPATH=/root/jiachenlong/backend
# 启动后端
cd /root/jiachenlong/backend
nohup python -m uvicorn app.main:app --host 0.0.0.0 --port 3000 > logs/api.log 2>&1 &
```
### 7. 重启Nginx
```bash
# 测试配置
nginx -t
# 重载配置
nginx -s reload
# 或完全重启
killall nginx && nginx
```
---
## SSL证书配置 (Let's Encrypt)
### 安装 Certbot
```bash
# CentOS/RHEL
yum install epel-release
yum install certbot python3-certbot-nginx
# 或使用 pip
pip install certbot certbot-nginx
```
### 获取证书
```bash
# 停止 Nginx如果正在运行
nginx -s stop
# 获取证书(单域名)
certbot certonly --standalone -d jiachenlong.com --agree-tos --email admin@jiachenlong.com --no-eff-email
# 获取证书(多域名)
certbot certonly --standalone -d jiachenlong.com -d www.jiachenlong.com --agree-tos --email admin@jiachenlong.com --no-eff-email
# 重启 Nginx
nginx
```
### 自动续期
```bash
# 测试续期dry-run
certbot renew --dry-run
# 设置定时任务(每天凌晨自动续期)
crontab -e
# 添加以下行:
# 0 3 * * * certbot renew --quiet --deploy-hook "nginx -s reload"
```
### Nginx HTTPS 配置
```nginx
server {
listen 80;
server_name jiachenlong.com www.jiachenlong.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name jiachenlong.com www.jiachenlong.com;
# SSL证书
ssl_certificate /etc/letsencrypt/live/jiachenlong.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jiachenlong.com/privkey.pem;
# SSL安全配置
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:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
# ... 其余配置同上 ...
}
```
---
## 数据库迁移 (Alembic)
### 查看当前版本
```bash
cd /root/jiachenlong/backend
source /opt/conda/etc/profile.d/conda.sh && conda activate py312
export PYTHONPATH=/root/jiachenlong/backend
alembic current
```
### 查看迁移历史
```bash
alembic history --verbose
```
### 创建新迁移
```bash
# 自动生成迁移脚本(根据模型变更)
alembic revision --autogenerate -m "描述变更内容"
# 手动创建空白迁移
alembic revision -m "描述变更内容"
```
### 执行迁移
```bash
# 升级到最新版本
alembic upgrade head
# 升级到指定版本
alembic upgrade <revision_id>
# 检查是否有待执行迁移
alembic check
```
### 回滚
```bash
# 回滚一步
alembic downgrade -1
# 回滚到初始状态
alembic downgrade base
```
### 生产环境迁移流程
```bash
# 1. 在测试环境验证迁移
alembic upgrade head
# 2. 检查数据完整性
# (在测试环境执行应用相关测试)
# 3. 在生产环境执行迁移(建议在低峰期)
alembic upgrade head
# 4. 重启后端服务
pkill -f 'uvicorn app.main:app'
nohup python -m uvicorn app.main:app --host 0.0.0.0 --port 3000 > logs/api.log 2>&1 &
```
---
## 常见问题与解决方案
### 1. 后端启动失败:`address already in use`
**原因**:端口被占用
**解决**
```bash
# 查看占用进程
fuser 3000/tcp
# 杀死占用进程
fuser -k 3000/tcp
```
### 2. 后端启动失败:`ModuleNotFoundError: No module named 'xxx'`
**原因**Python依赖缺失
**解决**
```bash
pip install -r requirements.txt
# 或安装特定依赖
pip install bcrypt passlib python-jose python-multipart email-validator oss2 Pillow
```
### 3. API返回500错误`name 'response' is not defined`
**原因**FastAPI函数参数中使用了`response: Response = None`,但该参数已被废弃或删除
**解决**:检查并修复 `app/routers/*.py` 文件中的 `response.headers` 使用
```python
# 找到类似代码
response.headers['X-Total-Pages'] = str(total_pages)
# 删除这些行(它们不是必需的)
```
### 4. 数据库连接失败:`could not translate host name`
**原因**:主机名未正确解析
**解决**:确保 `.env` 中的数据库地址使用完整域名
```bash
# 错误
DB_HOST=pgm-bp1t5w248t7s1pvr
# 正确
DB_HOST=pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com
```
### 5. 数据库连接失败:密码中特殊字符问题
**原因**:密码中的 `@` 符号导致URL解析错误
**解决**URL编码密码
```bash
# 密码 Passwd1@3 编码为 Passwd1%403
DATABASE_URL=postgresql://jiachenlong:Passwd1%403@...
```
### 6. 前端403 Forbidden
**原因**:文件权限问题
**解决**
```bash
chown -R nginx:nginx /var/www/html
chmod -R 755 /var/www/html
```
### 7. Nginx配置错误`server directive is not allowed here`
**原因**nginx配置文件放在HTTP块外面
**解决**确保server块在http块内部
### 8. 前端显示旧版本
**原因**:浏览器缓存
**解决**:强制刷新 (Ctrl+Shift+R) 或清除缓存
### 9. 后端日志显示数据库连接超时
**原因**:数据库地址不可达或网络问题
**解决**
```bash
# 测试连接
telnet pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com 5432
# 或
nc -zv pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com 5432
```
### 10. 文件上传失败 413 Request Entity Too Large
**原因**Nginx `client_max_body_size` 限制
**解决**:在 nginx.conf 的 http 或 server 块中添加:
```nginx
client_max_body_size 50M;
```
---
## 代码修改注意事项
### information.py / collections.py 常见问题
1. **Response参数问题**
- 函数签名中的 `response: Response = None` 会导致 `NameError`
- 如果不需要修改响应头,应该直接删除这个参数
- 同时删除函数体内使用 `response.headers` 的代码
2. **处理方法**
```python
# 错误写法
def get_list(response: Response = None):
response.headers['X-Total'] = '100' # 会报错
# 正确写法
def get_list():
# 不使用response.headers或使用Response参数的正确方式
pass
```
### collections.py 统计接口
- `get_current_user` 可能返回 `None`
- 访问 `current_user.role` 前必须检查 `current_user` 是否为 `None`
```python
# 错误
if current_user.role == "admin":
# 正确
if not current_user or current_user.role != "admin":
return {"totalCount": 0}
```
---
## 改进建议(已完成)
- [x] 使用 `python-dotenv` 管理环境变量 → `backend/.env.example`
- [x] Alembic 数据库迁移管理 → `backend/alembic/`
- [x] 单元测试框架 → `backend/tests/`
- [ ] 自动化部署脚本 (deploy.sh)
- [ ] CI/CD 自动化测试
- [ ] 健康检查端点
---
## 快速命令参考
```bash
# ========== 后端管理 ==========
# 查看后端进程
ps aux | grep uvicorn | grep -v grep
# 查看后端日志
tail -f /root/jiachenlong/backend/logs/api.log
# 重启后端
pkill -f 'uvicorn app.main:app'
cd /root/jiachenlong/backend
source /opt/conda/etc/profile.d/conda.sh && conda activate py312
export PYTHONPATH=/root/jiachenlong/backend
nohup python -m uvicorn app.main:app --host 0.0.0.0 --port 3000 > logs/api.log 2>&1 &
# ========== 测试API ==========
curl http://localhost:3000/api/collections/stats
curl http://localhost:3000/api/information/list?info_type=seek
# ========== Nginx ==========
nginx -t # 测试配置
nginx -s reload # 重载配置
nginx -s stop # 停止
killall nginx && nginx # 完全重启
# ========== 数据库迁移 ==========
cd /root/jiachenlong/backend
export PYTHONPATH=/root/jiachenlong/backend
alembic current # 查看当前版本
alembic history # 查看历史
alembic upgrade head # 执行迁移
alembic downgrade -1 # 回滚一步
# ========== SSL证书 ==========
certbot renew --dry-run # 测试续期
certbot renew --quiet # 执行续期
```
---
*最后更新2026-04-12*