DEPLOYMENT.md 19 KB

生产环境部署文档

目录


服务器信息

  • 服务器地址: 121.43.228.102
  • 后端端口: 8000
  • 数据库: MySQL (121.43.228.102:3306)

环境准备

1. 系统要求

  • 操作系统: Linux (推荐 Ubuntu 20.04+ 或 CentOS 7+)
  • Python: 3.11+
  • Node.js: 18+ (用于前端构建)
  • Nginx: 1.18+
  • MySQL: 5.7+ 或 8.0+

2. 安装依赖

# 更新系统
sudo apt update && sudo apt upgrade -y  # Ubuntu/Debian
# 或
sudo yum update -y  # CentOS/RHEL

# 安装 Python 3.11+
sudo apt install python3.11 python3.11-venv python3-pip -y  # Ubuntu/Debian
# 或
sudo yum install python311 python311-pip -y  # CentOS/RHEL

# 安装 Node.js 18+
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -  # Ubuntu/Debian
sudo apt install -y nodejs
# 或
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -  # CentOS/RHEL
sudo yum install -y nodejs

# 安装 Nginx
sudo apt install nginx -y  # Ubuntu/Debian
# 或
sudo yum install nginx -y  # CentOS/RHEL

# 安装 MySQL 客户端(用于测试连接)
sudo apt install mysql-client -y  # Ubuntu/Debian
# 或
sudo yum install mysql -y  # CentOS/RHEL

# 安装 uv (Python 包管理器)
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.cargo/env  # 或重新登录

3. 创建目录结构

# 创建项目根目录
sudo mkdir -p /iflytek/dibang
sudo chown -R $USER:$USER /iflytek/dibang

# 创建子目录
mkdir -p /iflytek/dibang/{api,web,app}

数据库配置

1. 数据库连接信息

{
    'host': '121.43.228.102',
    'port': 3306,
    'user': 'root',
    'password': 'hn02le.34lkdLKD',
    'database': 'dibang',
    'charset': 'utf8mb4'
}

2. 测试数据库连接

mysql -h 121.43.228.102 -P 3306 -u root -p'hn02le.34lkdLKD' -e "SHOW DATABASES;"

3. 创建数据库(如果不存在)

mysql -h 121.43.228.102 -P 3306 -u root -p'hn02le.34lkdLKD' -e "CREATE DATABASE IF NOT EXISTS dibang CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

后端部署

1. 上传后端代码

将后端代码上传到 /iflytek/dibang/api 目录:

# 假设代码在本地 backend 目录
scp -r backend/* user@121.43.228.102:/iflytek/dibang/api/

2. 创建虚拟环境并安装依赖

cd /iflytek/dibang/api

# 使用 uv 安装依赖(推荐)
uv sync --no-dev

# 或使用传统方式
python3.11 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e .

3. 配置环境变量

创建 .env 文件:

cd /iflytek/dibang/api
cp env.example .env
nano .env  # 或使用 vim

.env 文件内容:

# ============================================
# 环境配置
# ============================================
ENV=prod

# ============================================
# 数据库配置
# ============================================
DATABASE_URL=mysql+asyncmy://root:hn02le.34lkdLKD@121.43.228.102:3306/dibang-test?charset=utf8mb4

# ============================================
# JWT 配置
# ============================================
# 生产环境必须使用强密钥(至少32个字符)
JWT_SECRET=your-very-strong-secret-key-change-this-in-production-min-32-chars
ACCESS_TOKEN_EXPIRES_MINUTES=60
REFRESH_TOKEN_EXPIRES_DAYS=14

# ============================================
# 服务器配置
# ============================================
HOST=0.0.0.0
PORT=8000

# ============================================
# CORS 配置
# ============================================
# 生产环境建议指定具体域名,不要使用 *
CORS_ORIGINS=https://your-domain.com,https://h5.your-domain.com
CORS_ALLOW_CREDENTIALS=true
CORS_ALLOW_METHODS=GET,POST,PUT,DELETE,OPTIONS
CORS_ALLOW_HEADERS=*

# ============================================
# 数据库连接池配置
# ============================================
DB_POOL_SIZE=10
DB_MAX_OVERFLOW=20
DB_POOL_TIMEOUT=30
DB_POOL_RECYCLE=3600
DB_POOL_PRE_PING=true

重要: 请修改 JWT_SECRET 为一个强随机密钥!

4. 初始化数据库

cd /iflytek/dibang/api
source .venv/bin/activate  # 如果使用传统方式

# 运行数据库迁移(如果有)
# alembic upgrade head

# 或直接运行应用,会自动初始化模型
python app/main.py

5. 测试后端服务

# 启动服务测试
cd /iflytek/dibang/api
source .venv/bin/activate  # 如果使用传统方式
python app/main.py

# 在另一个终端测试
curl http://localhost:8000/
curl http://localhost:8000/api/health  # 如果有健康检查端点

前端部署

0. 配置生产环境变量(重要!)

在打包之前,需要在两个前端项目中创建 .env.production 文件来配置生产环境的 API 地址。

0.1 Web 端配置

在 art-design-pro 目录下创建 .env.production 文件:

cd art-design-pro
cat > .env.production << 'EOF'
# API 地址(推荐使用相对路径,由 Nginx 代理)
VITE_API_URL=/api
# 应用版本号(可选)
VITE_VERSION=1.0.0
EOF

0.2 H5 移动端配置

在 mobile-h5 目录下创建 .env.production 文件:

cd mobile-h5
cat > .env.production << 'EOF'
# API 地址(推荐使用相对路径,由 Nginx 代理)
VITE_API_URL=/api
EOF

重要说明:

  • VITE_API_URL=/api 表示使用相对路径,Nginx 会自动将 /api 请求代理到后端
  • 如果使用完整 URL(如 http://121.43.228.102:8000),需要配置后端 CORS,且不推荐
  • 详细配置说明请参考 FRONTEND_BUILD_CONFIG.md

1. Web 前端部署

1.1 本地构建

在本地开发机器上构建 Web 前端:

cd art-design-pro

# 确保已创建 .env.production 文件(见上面步骤)

# 安装依赖(如果还没安装)
npm install

# 打包
npm run build

1.2 上传构建文件

将构建后的 dist 目录内容上传到服务器:

# 上传构建文件
scp -r art-design-pro/dist/* user@121.43.228.102:/iflytek/dibang/web/

2. H5 移动端部署

2.1 本地构建

在本地开发机器上构建 H5 前端:

cd mobile-h5

# 确保已创建 .env.production 文件(见上面步骤)

# 安装依赖(如果还没安装)
npm install

# 打包
npm run build

2.2 上传构建文件

将构建后的 dist 目录内容上传到服务器:

# 上传构建文件
scp -r mobile-h5/dist/* user@121.43.228.102:/iflytek/dibang/app/

3. 设置文件权限

# 设置 Nginx 用户权限
sudo chown -R www-data:www-data /iflytek/dibang/web
sudo chown -R www-data:www-data /iflytek/dibang/app
sudo chmod -R 755 /iflytek/dibang/web
sudo chmod -R 755 /iflytek/dibang/app

Nginx 配置

1. 创建 Nginx 配置文件

创建主配置文件 /etc/nginx/sites-available/dibang:

sudo nano /etc/nginx/sites-available/dibang

2. Nginx Server 配置

# Web 前端配置
server {
    listen 80;
    server_name your-domain.com;  # 替换为实际域名

    # 如果需要 HTTPS,取消注释以下配置并配置 SSL 证书
    # listen 443 ssl http2;
    # ssl_certificate /path/to/ssl/cert.pem;
    # ssl_certificate_key /path/to/ssl/key.pem;
    # ssl_protocols TLSv1.2 TLSv1.3;
    # ssl_ciphers HIGH:!aNULL:!MD5;

    # 日志配置
    access_log /var/log/nginx/dibang-web-access.log;
    error_log /var/log/nginx/dibang-web-error.log;

    # Web 前端根目录
    root /iflytek/dibang/web;
    index index.html;

    # 前端静态文件
    location / {
        try_files $uri $uri/ /index.html;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";
    }

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # API 代理到后端
    location /api {
        proxy_pass http://127.0.0.1:8000;
        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 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # 缓冲设置
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # 健康检查端点
    location /health {
        proxy_pass http://127.0.0.1:8000/;
        proxy_set_header Host $host;
        access_log off;
    }
}

# H5 移动端配置
server {
    listen 80;
    server_name h5.your-domain.com;  # 替换为实际 H5 域名

    # 如果需要 HTTPS,取消注释以下配置并配置 SSL 证书
    # listen 443 ssl http2;
    # ssl_certificate /path/to/ssl/cert.pem;
    # ssl_certificate_key /path/to/ssl/key.pem;
    # ssl_protocols TLSv1.2 TLSv1.3;
    # ssl_ciphers HIGH:!aNULL:!MD5;

    # 日志配置
    access_log /var/log/nginx/dibang-h5-access.log;
    error_log /var/log/nginx/dibang-h5-error.log;

    # H5 前端根目录
    root /iflytek/dibang/app;
    index index.html;

    # 前端静态文件
    location / {
        try_files $uri $uri/ /index.html;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";
    }

    # 静态资源缓存
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # API 代理到后端
    location /api {
        proxy_pass http://127.0.0.1:8000;
        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 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # 缓冲设置
        proxy_buffering off;
        proxy_request_buffering off;
    }

    # 健康检查端点
    location /health {
        proxy_pass http://127.0.0.1:8000/;
        proxy_set_header Host $host;
        access_log off;
    }
}

3. 启用配置

# 创建符号链接
sudo ln -s /etc/nginx/sites-available/dibang /etc/nginx/sites-enabled/

# 测试 Nginx 配置
sudo nginx -t

# 重新加载 Nginx
sudo systemctl reload nginx
# 或
sudo service nginx reload

4. 如果使用 IP 访问(无域名)

如果暂时没有域名,可以使用 IP 访问,配置如下:

# Web 前端配置(IP 访问)
server {
    listen 80;
    server_name 121.43.228.102;

    access_log /var/log/nginx/dibang-web-access.log;
    error_log /var/log/nginx/dibang-web-error.log;

    root /iflytek/dibang/web;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location /api {
        proxy_pass http://127.0.0.1:8000;
        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 60s;
    }
}

# H5 移动端配置(使用路径区分)
server {
    listen 80;
    server_name 121.43.228.102;

    # Web 前端
    location / {
        root /iflytek/dibang/web;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    # H5 移动端
    location /app {
        alias /iflytek/dibang/app;
        index index.html;
        try_files $uri $uri/ /app/index.html;
    }

    # API 代理
    location /api {
        proxy_pass http://127.0.0.1:8000;
        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;
    }

    # 静态资源
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
}

服务管理

1. 使用 systemd 管理后端服务

创建 systemd 服务文件 /etc/systemd/system/dibang-backend.service:

sudo nano /etc/systemd/system/dibang-backend.service

服务文件内容:

[Unit]
Description=Dibang Backend API Service
After=network.target mysql.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/iflytek/dibang/api
Environment="PATH=/iflytek/dibang/api/.venv/bin:/usr/local/bin:/usr/bin:/bin"
ExecStart=/iflytek/dibang/api/.venv/bin/python app/main.py
# 或使用 uv
# ExecStart=/home/$USER/.cargo/bin/uv run python app/main.py

Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=dibang-backend

# 安全设置
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

启用并启动服务:

# 重新加载 systemd
sudo systemctl daemon-reload

# 启用服务(开机自启)
sudo systemctl enable dibang-backend

# 启动服务
sudo systemctl start dibang-backend

# 查看状态
sudo systemctl status dibang-backend

# 查看日志
sudo journalctl -u dibang-backend -f

2. 使用 Supervisor(可选)

如果使用 Supervisor,创建配置文件 /etc/supervisor/conf.d/dibang-backend.conf:

[program:dibang-backend]
command=/iflytek/dibang/api/.venv/bin/python app/main.py
directory=/iflytek/dibang/api
user=www-data
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/dibang-backend.log
environment=PATH="/iflytek/dibang/api/.venv/bin:/usr/local/bin:/usr/bin:/bin"

然后:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start dibang-backend

3. 使用 Gunicorn(生产环境推荐)

如果需要更好的性能,可以使用 Gunicorn + Uvicorn workers:

# 安装 gunicorn
cd /iflytek/dibang/api
source .venv/bin/activate
pip install gunicorn

# 创建启动脚本
cat > /iflytek/dibang/api/start.sh << 'EOF'
#!/bin/bash
cd /iflytek/dibang/api
source .venv/bin/activate
gunicorn app.main:app \
    --workers 4 \
    --worker-class uvicorn.workers.UvicornWorker \
    --bind 0.0.0.0:8000 \
    --access-logfile - \
    --error-logfile - \
    --log-level info \
    --timeout 120 \
    --keep-alive 5
EOF

chmod +x /iflytek/dibang/api/start.sh

然后修改 systemd 服务文件的 ExecStart:

ExecStart=/iflytek/dibang/api/start.sh

验证部署

1. 检查后端服务

# 检查服务状态
sudo systemctl status dibang-backend

# 检查端口监听
sudo netstat -tlnp | grep 8000
# 或
sudo ss -tlnp | grep 8000

# 测试 API
curl http://localhost:8000/
curl http://localhost:8000/api/health  # 如果有健康检查端点

2. 检查 Nginx

# 检查 Nginx 状态
sudo systemctl status nginx

# 测试配置
sudo nginx -t

# 查看日志
sudo tail -f /var/log/nginx/dibang-web-access.log
sudo tail -f /var/log/nginx/dibang-web-error.log

3. 检查前端访问

在浏览器中访问:

  • Web 前端: http://121.43.228.102 或 http://your-domain.com
  • H5 移动端: http://121.43.228.102/app 或 http://h5.your-domain.com
  • API 测试: http://121.43.228.102/api/

4. 防火墙配置

确保防火墙允许必要的端口:

# Ubuntu/Debian (ufw)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8000/tcp  # 如果需要在外部访问后端(不推荐,应通过 Nginx)

# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

常见问题

1. 后端服务无法启动

  • 检查 .env 文件配置是否正确
  • 检查数据库连接是否正常
  • 查看日志: sudo journalctl -u dibang-backend -n 50

2. Nginx 502 Bad Gateway

  • 检查后端服务是否运行: sudo systemctl status dibang-backend
  • 检查后端端口: sudo netstat -tlnp | grep 8000
  • 检查 Nginx 错误日志: sudo tail -f /var/log/nginx/dibang-web-error.log

3. 静态文件 404

  • 检查文件路径和权限
  • 确认 Nginx 配置中的 root 路径正确
  • 检查文件所有者: ls -la /iflytek/dibang/web

4. CORS 错误

  • 检查后端 .env 中的 CORS_ORIGINS 配置
  • 确保前端请求的域名在允许列表中

5. 数据库连接失败

  • 检查数据库服务器是否可访问: telnet 121.43.228.102 3306
  • 检查数据库用户权限
  • 检查防火墙规则

更新部署

更新后端

# 1. 停止服务
sudo systemctl stop dibang-backend

# 2. 备份当前代码
cp -r /iflytek/dibang/api /iflytek/dibang/api.backup.$(date +%Y%m%d)

# 3. 上传新代码
# scp -r backend/* user@121.43.228.102:/iflytek/dibang/api/

# 4. 更新依赖(如果需要)
cd /iflytek/dibang/api
source .venv/bin/activate
pip install -e .

# 5. 运行数据库迁移(如果有)
# alembic upgrade head

# 6. 启动服务
sudo systemctl start dibang-backend

# 7. 检查状态
sudo systemctl status dibang-backend

更新前端

# 1. 备份当前文件
cp -r /iflytek/dibang/web /iflytek/dibang/web.backup.$(date +%Y%m%d)
cp -r /iflytek/dibang/app /iflytek/dibang/app.backup.$(date +%Y%m%d)

# 2. 上传新构建文件
# scp -r art-design-pro/dist/* user@121.43.228.102:/iflytek/dibang/web/
# scp -r mobile-h5/dist/* user@121.43.228.102:/iflytek/dibang/app/

# 3. 设置权限
sudo chown -R www-data:www-data /iflytek/dibang/web
sudo chown -R www-data:www-data /iflytek/dibang/app

# 4. 重新加载 Nginx(通常不需要,但可以清除缓存)
sudo systemctl reload nginx

安全建议

  1. 使用 HTTPS: 配置 SSL 证书,启用 HTTPS
  2. 修改 JWT_SECRET: 使用强随机密钥
  3. 限制 CORS: 生产环境不要使用 *,指定具体域名
  4. 防火墙: 只开放必要端口,后端 8000 端口不应对外暴露
  5. 数据库安全: 使用专用数据库用户,限制权限
  6. 定期备份: 设置数据库和代码的定期备份
  7. 日志监控: 定期检查日志,监控异常访问
  8. 更新系统: 定期更新系统和依赖包

备份策略

数据库备份

# 创建备份脚本
cat > /iflytek/dibang/backup_db.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/iflytek/dibang/backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

mysqldump -h 121.43.228.102 -P 3306 -u root -p'hn02le.34lkdLKD' \
    dibang > $BACKUP_DIR/dibang_$DATE.sql

# 压缩备份
gzip $BACKUP_DIR/dibang_$DATE.sql

# 删除 7 天前的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
EOF

chmod +x /iflytek/dibang/backup_db.sh

# 添加到 crontab(每天凌晨 2 点备份)
# crontab -e
# 0 2 * * * /iflytek/dibang/backup_db.sh

联系信息

如有问题,请联系运维团队或查看项目文档。