jiachenlong/docs/DEPLOYMENT.md

14 KiB
Raw Blame History

甲辰藏品管理系统 部署手册

当前版本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@3Passwd1%403
  • Coolbot123 无需编码

OSS存储

  • Bucket: jiachenlong-oss

环境变量 (.env)

📁 完整示例见 backend/.env.example

数据库配置

# 主数据库 - 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)

# 用于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_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

部署流程

1. 获取代码

# 克隆仓库
git clone http://caibotd:Caibotd123@101.37.160.219/root/jiachenlong.git

# 切换到目标版本
cd jiachenlong
git checkout v1.2.88  # 或指定版本tag

2. 构建前端

cd frontend
npm install
npm run build

3. 配置后端环境变量

在后端服务器创建 .env 文件:

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. 上传文件到服务器

# 上传前端
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)

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. 启动后端服务

# 激活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

# 测试配置
nginx -t

# 重载配置
nginx -s reload

# 或完全重启
killall nginx && nginx

SSL证书配置 (Let's Encrypt)

安装 Certbot

# CentOS/RHEL
yum install epel-release
yum install certbot python3-certbot-nginx

# 或使用 pip
pip install certbot certbot-nginx

获取证书

# 停止 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

自动续期

# 测试续期dry-run
certbot renew --dry-run

# 设置定时任务(每天凌晨自动续期)
crontab -e
# 添加以下行:
# 0 3 * * * certbot renew --quiet --deploy-hook "nginx -s reload"

Nginx HTTPS 配置

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)

查看当前版本

cd /root/jiachenlong/backend
source /opt/conda/etc/profile.d/conda.sh && conda activate py312
export PYTHONPATH=/root/jiachenlong/backend

alembic current

查看迁移历史

alembic history --verbose

创建新迁移

# 自动生成迁移脚本(根据模型变更)
alembic revision --autogenerate -m "描述变更内容"

# 手动创建空白迁移
alembic revision -m "描述变更内容"

执行迁移

# 升级到最新版本
alembic upgrade head

# 升级到指定版本
alembic upgrade <revision_id>

# 检查是否有待执行迁移
alembic check

回滚

# 回滚一步
alembic downgrade -1

# 回滚到初始状态
alembic downgrade base

生产环境迁移流程

# 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

原因:端口被占用

解决

# 查看占用进程
fuser 3000/tcp

# 杀死占用进程
fuser -k 3000/tcp

2. 后端启动失败:ModuleNotFoundError: No module named 'xxx'

原因Python依赖缺失

解决

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 使用

# 找到类似代码
response.headers['X-Total-Pages'] = str(total_pages)

# 删除这些行(它们不是必需的)

4. 数据库连接失败:could not translate host name

原因:主机名未正确解析

解决:确保 .env 中的数据库地址使用完整域名

# 错误
DB_HOST=pgm-bp1t5w248t7s1pvr

# 正确
DB_HOST=pgm-bp1t5w248t7s1pvr.pg.rds.aliyuncs.com

5. 数据库连接失败:密码中特殊字符问题

原因:密码中的 @ 符号导致URL解析错误

解决URL编码密码

# 密码 Passwd1@3 编码为 Passwd1%403
DATABASE_URL=postgresql://jiachenlong:Passwd1%403@...

6. 前端403 Forbidden

原因:文件权限问题

解决

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. 后端日志显示数据库连接超时

原因:数据库地址不可达或网络问题

解决

# 测试连接
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 块中添加:

client_max_body_size 50M;

代码修改注意事项

information.py / collections.py 常见问题

  1. Response参数问题

    • 函数签名中的 response: Response = None 会导致 NameError
    • 如果不需要修改响应头,应该直接删除这个参数
    • 同时删除函数体内使用 response.headers 的代码
  2. 处理方法

# 错误写法
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
# 错误
if current_user.role == "admin":

# 正确
if not current_user or current_user.role != "admin":
    return {"totalCount": 0}

改进建议(已完成)

  • 使用 python-dotenv 管理环境变量 → backend/.env.example
  • Alembic 数据库迁移管理 → backend/alembic/
  • 单元测试框架 → backend/tests/
  • 自动化部署脚本 (deploy.sh)
  • CI/CD 自动化测试
  • 健康检查端点

快速命令参考

# ========== 后端管理 ==========
# 查看后端进程
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