Files
goal-planner/DEPLOY.md
T
2026-11-02 15:45:49 +08:00

481 lines
12 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.
# Goal Planner Linux 部署指南
## 环境要求
### 服务器
- Linux 服务器(Ubuntu 20.04+ / CentOS 7+)
- Python 3.11+(由 uv 管理,不依赖系统 Python)
- MySQL 5.7+ / 8.0(需提前安装)
- Nginx(需提前安装)
- [uv](https://docs.astral.sh/uv/)(Python 包管理工具)
> **关于 Python 版本**:项目要求 Python ≥ 3.10。CentOS 7 系统自带 Python 2.7.5,无需升级或卸载,uv 会自动下载和管理独立的 Python 版本,不会与系统 Python 冲突。系统工具(如 yum)依赖的 Python 2.7.5 完全不受影响。**推荐使用 Python 3.11**,wheel 生态最成熟,所有依赖都有预编译 wheel,安装秒完成;Python 3.12/3.14 部分包(如 greenlet、pydantic-core)在 CentOS 7 上缺少兼容的预编译 wheel,需要从源码编译,而 CentOS 7 的 GCC 4.8.5 不支持 C++11,会导致编译失败。
### 本地(仅构建前端时需要)
- Node.js 18+
---
## 1. 安装 uv
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
安装完成后,需要让 uv 命令生效(二选一):
```bash
# 方式一:执行以下命令(推荐,立即生效)
source $HOME/.local/bin/env
# 方式二:重新连接 SSH
```
验证安装:
```bash
uv --version
```
---
## 2. 配置 MySQL
```bash
# 登录 MySQL
sudo mysql -u root -p
# 创建数据库和用户
CREATE DATABASE goal_planner CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'goal_planner'@'localhost' IDENTIFIED BY '你的数据库密码';
GRANT ALL PRIVILEGES ON goal_planner.* TO 'goal_planner'@'localhost';
FLUSH PRIVILEGES;
EXIT;
```
> 首次启动后端时,SQLAlchemy 会自动创建表结构,无需手动导入。
---
## 3. 上传项目
将项目上传到服务器,部署目录为 `/home/wwwroot/goal-planner`:
```bash
sudo mkdir -p /home/wwwroot/goal-planner
# 方式一:git clone
cd /home/wwwroot/goal-planner
git clone <你的仓库地址> .
# 方式二:scp 上传
# scp -r ./goal-planner/* user@server:/home/wwwroot/goal-planner/
```
---
## 4. 后端部署
### 4.1 配置环境变量
```bash
cd /home/wwwroot/goal-planner/backend
cp .env.example .env
```
编辑 `.env` 文件:
```bash
vi .env
```
填入实际配置:
```env
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=goal_planner
MYSQL_PASSWORD=你的数据库密码
MYSQL_DATABASE=goal_planner
SECRET_KEY=替换为一个随机长字符串
ACCESS_TOKEN_EXPIRE_MINUTES=1440
LLM_PROVIDER=dashscope
OPENAI_API_KEY=你的API密钥
OPENAI_API_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
OPENAI_MODEL=qwen3-plus
ENABLE_SEARCH=true
```
> **重要**:`SECRET_KEY` 必须替换为随机字符串,可用 `openssl rand -hex 32` 生成。
### 4.2 使用 uv 创建虚拟环境并安装依赖
```bash
cd /home/wwwroot/goal-planner
# 创建虚拟环境,uv 会自动下载 Python 3.11(不依赖系统 Python)
uv venv .venv --python 3.11
# 激活虚拟环境
source .venv/bin/activate
# 安装依赖(使用清华镜像加速,强制只安装预编译 wheel)
uv pip install -r backend/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --only-binary :all:
```
> **说明**:`uv venv --python 3.11` 会将 Python 3.11 下载到 `~/.local/share/uv/python/` 目录,仅 uv 使用,不会覆盖或修改系统自带的 Python 2.7.5。虚拟环境放在项目根目录 `/home/wwwroot/goal-planner/.venv`,与 backend 同级。`--only-binary :all:` 强制只安装预编译 wheel,避免在 CentOS 7 的旧 GCC 上从源码编译失败。
### 4.3 验证后端启动
```bash
cd /home/wwwroot/goal-planner/backend
source /home/wwwroot/goal-planner/.venv/bin/activate
uvicorn main:app --host 127.0.0.1 --port 8000
```
看到 `Uvicorn running on http://127.0.0.1:8000` 即启动成功,`Ctrl+C` 停止。
### 4.4 后台运行
验证无误后,使用以下方式后台运行(推荐方式二):
**方式一:nohup(简单快速)**
```bash
cd /home/wwwroot/goal-planner/backend
source /home/wwwroot/goal-planner/.venv/bin/activate
nohup uvicorn main:app --host 127.0.0.1 --port 8000 > /home/wwwroot/goal-planner/backend/app.log 2>&1 &
```
常用操作:
```bash
# 查看日志
tail -f /home/wwwroot/goal-planner/backend/app.log
# 查看进程
ps aux | grep uvicorn
# 停止服务
kill $(ps aux | grep 'uvicorn main:app' | grep -v grep | awk '{print $2}')
```
**方式二:systemd 服务(推荐,开机自启 + 自动重启)**
见第 7 章。
---
## 5. 前端构建与部署
### 5.1 修改 API 接口地址
前端 API 地址硬编码在 `frontend/services/apiService.ts` 中:
```typescript
const API_BASE_URL = 'http://localhost:8000';
```
**部署前必须修改为实际的后端地址**。根据你的部署方式选择:
#### 方式一:使用 Nginx 反向代理(推荐)
将 API 地址改为相对路径,由 Nginx 统一代理:
```typescript
const API_BASE_URL = '/api-proxy';
```
这样前端请求 `/api-proxy/api/generate/` 会被 Nginx 转发到后端 `http://127.0.0.1:8000/api/generate/`,无需暴露后端端口。
#### 方式二:直接指向后端地址
如果你的后端运行在独立域名或端口上:
```typescript
const API_BASE_URL = 'http://你的服务器IP:8000';
```
> **注意**:此方式需要后端开放 8000 端口,并在 `main.py` 的 CORS 配置中添加前端域名。
### 5.2 修改后端 CORS 配置(方式一不需要)
如果使用方式二,需要修改 `backend/main.py` 中的 CORS 允许来源:
```python
origins = [
"http://你的域名",
"http://你的服务器IP",
]
```
### 5.3 本地构建前端
在本地开发机器上执行构建(不需要在服务器上安装 Node.js):
```bash
cd frontend
# 安装依赖
npm install
# 构建
npm run build
```
构建产物在 `frontend/dist/` 目录中。
### 5.4 上传静态文件到服务器
将本地构建产物上传到服务器:
```bash
# 在本地执行
scp -r frontend/dist/* user@你的服务器IP:/var/www/goal-planner/
```
或在服务器上从项目目录复制(如果已上传整个项目):
```bash
sudo mkdir -p /var/www/goal-planner
sudo cp -r /home/wwwroot/goal-planner/frontend/dist/* /var/www/goal-planner/
```
---
## 6. 配置 Nginx
创建 Nginx 配置文件:
```bash
sudo vi /etc/nginx/conf.d/goal-planner.conf
```
### 方式一:Nginx 反向代理(推荐)
前后端统一通过 Nginx 访问,后端不对外暴露端口:
```nginx
server {
listen 80;
server_name 你的域名或IP;
# 前端静态文件
root /var/www/goal-planner;
index index.html;
# 前端路由 - SPA 应用所有路径都返回 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 后端 API 反向代理
location /api-proxy/ {
rewrite ^/api-proxy/(.*) /$1 break;
proxy_pass http://127.0.0.1:8000;
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;
# SSE 支持 - 关键配置
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Connection '';
}
# 静态资源缓存
location /assets/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}
```
> **SSE 关键配置说明**:
> - `proxy_buffering off` — 禁用缓冲,确保 SSE 事件实时推送到客户端
> - `proxy_cache off` — 禁用缓存
> - `proxy_read_timeout 300s` — AI 生成可能耗时较长,增大超时时间
> - `proxy_http_version 1.1` + `Connection ''` — 保持长连接
### 方式二:前后端分离部署
后端直接监听 8000 端口对外服务:
```nginx
server {
listen 80;
server_name 你的域名或IP;
root /var/www/goal-planner;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /assets/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
```
此方式下 `apiService.ts` 中的 `API_BASE_URL` 应设为 `http://你的域名或IP:8000`。
### 验证并重启 Nginx
```bash
sudo nginx -t
sudo systemctl restart nginx
```
---
## 7. 使用 systemd 管理后端进程
创建 systemd 服务文件,实现开机自启和进程管理:
```bash
sudo vi /etc/systemd/system/goal-planner.service
```
```ini
[Unit]
Description=Goal Planner Backend API
After=network.target mysql.service
[Service]
Type=simple
User=root
WorkingDirectory=/home/wwwroot/goal-planner/backend
ExecStart=/home/wwwroot/goal-planner/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
```
> 如果使用方式二(前后端分离),将 `--host 127.0.0.1` 改为 `--host 0.0.0.0` 以允许外部访问。
启动并设置开机自启:
```bash
sudo systemctl daemon-reload
sudo systemctl start goal-planner
sudo systemctl enable goal-planner
```
常用管理命令:
```bash
sudo systemctl status goal-planner # 查看状态
sudo systemctl restart goal-planner # 重启
sudo systemctl stop goal-planner # 停止
sudo journalctl -u goal-planner -f # 查看实时日志
```
---
## 8. 验证部署
```bash
# 检查后端健康状态
curl http://127.0.0.1:8000/api/health
# 预期返回: {"status":"ok"}
# 检查 Nginx 代理(方式一)
curl http://你的域名或IP/api-proxy/api/health
# 预期返回: {"status":"ok"}
# 浏览器访问
# http://你的域名或IP
```
---
## 9. HTTPS 配置(可选但推荐)
使用 Let's Encrypt 免费证书:
```bash
sudo apt install certbot python3-certbot-nginx # Ubuntu
sudo yum install certbot python3-certbot-nginx # CentOS
sudo certbot --nginx -d 你的域名
```
Certbot 会自动修改 Nginx 配置并配置 SSL 证书自动续期。
---
## 10. 更新部署
当代码更新后,执行以下步骤:
### 后端更新
```bash
# 服务器上拉取最新代码
cd /home/wwwroot/goal-planner
git pull
# 更新后端依赖(如有变动)
source /home/wwwroot/goal-planner/.venv/bin/activate
uv pip install -r backend/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --only-binary :all:
# 重启后端
sudo systemctl restart goal-planner
```
### 前端更新
```bash
# 本地构建
cd frontend
npm install
npm run build
# 上传到服务器
scp -r dist/* user@你的服务器IP:/var/www/goal-planner/
```
---
## 文件结构总览
```
/home/wwwroot/goal-planner/
├── .venv/ # uv 创建的 Python 虚拟环境(项目根目录)
├── backend/
│ ├── .env # 环境变量配置(含数据库密码、API密钥)
│ ├── .env.example # 环境变量模板
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置读取
│ ├── database.py # 数据库连接
│ ├── requirements.txt # Python 依赖
│ ├── models/ # 数据模型
│ └── routes/ # API 路由
│ ├── auth.py
│ ├── generate.py
│ └── plans.py
└── frontend/
├── dist/ # 构建产物 → 部署到 /var/www/goal-planner/
├── services/
│ └── apiService.ts # API 地址配置(需修改 API_BASE_URL)
├── package.json
└── vite.config.ts
/var/www/goal-planner/ # Nginx 静态文件目录
/etc/nginx/conf.d/goal-planner.conf # Nginx 配置
/etc/systemd/system/goal-planner.service # 后端服务配置
```