453 lines
10 KiB
Markdown
453 lines
10 KiB
Markdown
# 部署指南:腾讯云 + 1Panel + OpenResty + Gitea CI/CD
|
||
|
||
## 目录
|
||
|
||
1. [架构概览](#1-架构概览)
|
||
2. [服务器准备](#2-服务器准备)
|
||
3. [配置环境变量](#3-配置环境变量)
|
||
4. [创建数据库](#4-创建数据库)
|
||
5. [手动首次部署](#5-手动首次部署)
|
||
6. [在 1Panel 中配置 OpenResty](#6-在-1panel-中配置-openresty)
|
||
7. [DNS 解析配置](#7-dns-解析配置)
|
||
8. [配置 Gitea Actions CI/CD](#8-配置-gitea-actions-cicd)
|
||
9. [验证部署](#9-验证部署)
|
||
10. [日常运维](#10-日常运维)
|
||
|
||
---
|
||
|
||
## 1. 架构概览
|
||
|
||
```
|
||
用户浏览器
|
||
│
|
||
▼
|
||
OpenResty (1Panel 管理, SSL, 端口 80/443)
|
||
│
|
||
├── makefire.fun → 127.0.0.1:3001 (Frontend Nginx 容器)
|
||
└── api.makefire.fun → 127.0.0.1:8000 (Backend FastAPI 容器)
|
||
│
|
||
▼
|
||
PostgreSQL (1Panel 已有容器, 1panel-network)
|
||
```
|
||
|
||
**关键设计决策:**
|
||
- 后端和前端容器只绑定 `127.0.0.1`,不对外暴露,由 OpenResty 统一反代
|
||
- 所有容器加入 `1panel-network`,可直接通过 `postgresql` 主机名访问已有数据库
|
||
- 不使用 Traefik(用 1Panel 自带的 OpenResty 替代)
|
||
- 不启动独立 PostgreSQL 容器(复用已有的)
|
||
|
||
---
|
||
|
||
## 2. 服务器准备
|
||
|
||
### 2.1 创建部署目录
|
||
|
||
```bash
|
||
# SSH 登录服务器后执行
|
||
sudo mkdir -p /opt/fastapi-app
|
||
sudo chown $USER:$USER /opt/fastapi-app
|
||
```
|
||
|
||
### 2.2 初始化 Git 仓库(在 Gitea 上)
|
||
|
||
1. 登录 Gitea(`http://your-server-ip:3000`)
|
||
2. 创建新仓库,例如 `spatialhub`
|
||
3. 在本地开发机上添加 Gitea 远程仓库:
|
||
|
||
```bash
|
||
cd /Users/weifeng/Workspace/full-stack-fastapi-template
|
||
|
||
# 添加 Gitea 远程
|
||
git remote add gitea http://your-server-ip:3000/your-username/spatialhub.git
|
||
|
||
# 推送代码
|
||
git push gitea main
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 配置环境变量
|
||
|
||
### 3.1 在服务器上创建生产环境文件
|
||
|
||
```bash
|
||
cd /opt/fastapi-app
|
||
|
||
# 复制示例文件(首次需要从代码仓库获取)
|
||
cp .env.production.example .env.production
|
||
```
|
||
|
||
### 3.2 修改关键配置
|
||
|
||
```bash
|
||
nano .env.production
|
||
```
|
||
|
||
**必须修改的项:**
|
||
|
||
```bash
|
||
# 生成强随机密钥
|
||
SECRET_KEY=$(openssl rand -hex 32)
|
||
echo "生成的 SECRET_KEY: $SECRET_KEY"
|
||
|
||
# 设置强管理员密码
|
||
FIRST_SUPERUSER_PASSWORD=你的强密码
|
||
```
|
||
|
||
> ⚠️ `SECRET_KEY` 和 `FIRST_SUPERUSER_PASSWORD` 不能使用默认值 `changethis`,否则生产环境会报错。
|
||
|
||
---
|
||
|
||
## 4. 创建数据库
|
||
|
||
在已有的 PostgreSQL 中为本项目创建专用数据库:
|
||
|
||
```bash
|
||
# 方法一:使用 docker exec
|
||
docker exec -it 1Panel-postgresql-bxrK psql -U user_ZPKMQ6 -c "CREATE DATABASE app;"
|
||
|
||
# 验证数据库是否创建成功
|
||
docker exec -it 1Panel-postgresql-bxrK psql -U user_ZPKMQ6 -c "\l" | grep app
|
||
```
|
||
|
||
如果你想创建专用用户(更安全,可选):
|
||
|
||
```bash
|
||
docker exec -it 1Panel-postgresql-bxrK psql -U user_ZPKMQ6 -c "
|
||
CREATE USER fastapi_user WITH PASSWORD 'your_strong_password';
|
||
GRANT ALL PRIVILEGES ON DATABASE app TO fastapi_user;
|
||
ALTER DATABASE app OWNER TO fastapi_user;
|
||
"
|
||
```
|
||
|
||
> 如果使用专用用户,记得更新 `.env.production` 中的 `POSTGRES_USER` 和 `POSTGRES_PASSWORD`。
|
||
|
||
---
|
||
|
||
## 5. 手动首次部署
|
||
|
||
### 5.1 克隆代码到服务器
|
||
|
||
```bash
|
||
cd /opt/fastapi-app
|
||
git clone http://localhost:3000/your-username/spatialhub.git .
|
||
# 或者如果已经有代码
|
||
git pull origin main
|
||
```
|
||
|
||
### 5.2 复制环境变量文件
|
||
|
||
确保 `.env.production` 在 `/opt/fastapi-app/` 目录下。
|
||
|
||
### 5.3 构建和启动
|
||
|
||
```bash
|
||
cd /opt/fastapi-app
|
||
|
||
# 构建镜像
|
||
docker compose -f compose.prod.yml build
|
||
|
||
# 启动服务
|
||
docker compose -f compose.prod.yml up -d
|
||
|
||
# 查看日志
|
||
docker compose -f compose.prod.yml logs -f
|
||
```
|
||
|
||
### 5.4 验证容器状态
|
||
|
||
```bash
|
||
# 查看运行状态
|
||
docker compose -f compose.prod.yml ps
|
||
|
||
# 测试后端
|
||
curl http://127.0.0.1:8000/api/v1/utils/health-check/
|
||
|
||
# 测试前端
|
||
curl -I http://127.0.0.1:3001
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 在 1Panel 中配置 OpenResty
|
||
|
||
### 6.1 创建前端网站
|
||
|
||
1. 打开 1Panel → **网站** → **创建网站**
|
||
2. 选择 **反向代理**
|
||
3. 配置:
|
||
- **主域名**: `makefire.fun`
|
||
- **代理地址**: `http://127.0.0.1:3001`
|
||
4. 点击创建
|
||
|
||
### 6.2 创建后端 API 网站
|
||
|
||
1. **网站** → **创建网站** → **反向代理**
|
||
2. 配置:
|
||
- **主域名**: `api.makefire.fun`
|
||
- **代理地址**: `http://127.0.0.1:8000`
|
||
3. 点击创建
|
||
|
||
### 6.3 配置 SSL 证书
|
||
|
||
对每个网站:
|
||
|
||
1. 点击网站名称进入设置
|
||
2. 选择 **HTTPS** 标签
|
||
3. 选择 **申请证书** → **Let's Encrypt**
|
||
4. 勾选 **自动续签**
|
||
5. 勾选 **HTTP → HTTPS 强制跳转**
|
||
|
||
### 6.4 修改后端网站配置(可选优化)
|
||
|
||
进入 `api.makefire.fun` 网站设置 → **配置文件**,在 `location /` 块中添加:
|
||
|
||
```nginx
|
||
# WebSocket 支持
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
|
||
# 请求体大小限制
|
||
client_max_body_size 10m;
|
||
|
||
# 超时
|
||
proxy_connect_timeout 60s;
|
||
proxy_send_timeout 60s;
|
||
proxy_read_timeout 60s;
|
||
```
|
||
|
||
> 完整参考配置见项目根目录的 `openresty-example.conf`。
|
||
|
||
---
|
||
|
||
## 7. DNS 解析配置
|
||
|
||
在你的域名 DNS 管理处(腾讯云 DNS 或其他)添加:
|
||
|
||
| 记录类型 | 主机记录 | 记录值 | TTL |
|
||
|---------|---------|--------|-----|
|
||
| A | @ | 你的服务器 IP | 600 |
|
||
| A | api | 你的服务器 IP | 600 |
|
||
|
||
> 如果使用腾讯云域名,进入 **DNS 解析 DNSPod** 配置。
|
||
|
||
---
|
||
|
||
## 8. 配置 Gitea Actions CI/CD
|
||
|
||
### 8.1 安装 Gitea Actions Runner
|
||
|
||
```bash
|
||
# 1. 下载 Gitea Actions Runner
|
||
# 访问 https://gitea.com/gitea/act_runner/releases 获取最新版本
|
||
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
|
||
chmod +x act_runner-0.2.11-linux-amd64
|
||
sudo mv act_runner-0.2.11-linux-amd64 /usr/local/bin/act_runner
|
||
|
||
# 2. 生成配置文件
|
||
cd /opt
|
||
act_runner generate-config > act_runner_config.yaml
|
||
```
|
||
|
||
### 8.2 修改 Runner 配置
|
||
|
||
编辑 `/opt/act_runner_config.yaml`,关键修改:
|
||
|
||
```yaml
|
||
runner:
|
||
# 标签,决定 workflow 中 runs-on 可以匹配的值
|
||
labels:
|
||
- "ubuntu-latest:host"
|
||
# ↑ 使用 host 模式,直接在服务器上运行(不在 Docker 中套 Docker)
|
||
```
|
||
|
||
> **为什么用 `host` 模式?** 因为 workflow 需要执行 `docker compose` 命令来管理服务器上的容器。若在容器中运行,需要额外配置 Docker-in-Docker,对低内存服务器更加不友好。
|
||
|
||
### 8.3 注册 Runner
|
||
|
||
```bash
|
||
# 1. 在 Gitea 中获取 Runner Token
|
||
# 进入仓库 → Settings → Actions → Runners → 点击 "Create new runner"
|
||
# 复制显示的 Token
|
||
|
||
# 2. 注册
|
||
act_runner register \
|
||
--instance http://localhost:3000 \
|
||
--token YOUR_RUNNER_TOKEN \
|
||
--name my-runner \
|
||
--labels "ubuntu-latest:host" \
|
||
--config /opt/act_runner_config.yaml \
|
||
--no-interactive
|
||
|
||
# 3. 启动(测试)
|
||
act_runner daemon --config /opt/act_runner_config.yaml
|
||
```
|
||
|
||
### 8.4 设置为系统服务(推荐)
|
||
|
||
```bash
|
||
sudo tee /etc/systemd/system/gitea-runner.service << 'EOF'
|
||
[Unit]
|
||
Description=Gitea Actions Runner
|
||
After=network.target docker.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
WorkingDirectory=/opt/fastapi-app
|
||
ExecStart=/usr/local/bin/act_runner daemon --config /opt/act_runner_config.yaml
|
||
Restart=always
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable gitea-runner
|
||
sudo systemctl start gitea-runner
|
||
|
||
# 查看状态
|
||
sudo systemctl status gitea-runner
|
||
```
|
||
|
||
### 8.5 配置 Gitea Secrets
|
||
|
||
在 Gitea 仓库中配置环境变量密钥:
|
||
|
||
1. 进入仓库 → **Settings** → **Actions** → **Secrets**
|
||
2. 添加以下 Secrets:
|
||
|
||
| Secret 名称 | 值 |
|
||
|-------------|-----|
|
||
| `DOMAIN` | `makefire.fun` |
|
||
| `FRONTEND_HOST` | `https://makefire.fun` |
|
||
| `PROJECT_NAME` | `SpatialHub` |
|
||
| `STACK_NAME` | `spatialhub` |
|
||
| `BACKEND_CORS_ORIGINS` | `https://makefire.fun,https://api.makefire.fun` |
|
||
| `SECRET_KEY` | *(用 `openssl rand -hex 32` 生成)* |
|
||
| `FIRST_SUPERUSER` | `admin@makefire.fun` |
|
||
| `FIRST_SUPERUSER_PASSWORD` | *(你的强密码)* |
|
||
| `SMTP_HOST` | *(留空或填写)* |
|
||
| `SMTP_USER` | *(留空或填写)* |
|
||
| `SMTP_PASSWORD` | *(留空或填写)* |
|
||
| `EMAILS_FROM_EMAIL` | `info@makefire.fun` |
|
||
| `SMTP_TLS` | `True` |
|
||
| `SMTP_SSL` | `False` |
|
||
| `SMTP_PORT` | `587` |
|
||
| `POSTGRES_SERVER` | `postgresql` |
|
||
| `POSTGRES_PORT` | `5432` |
|
||
| `POSTGRES_DB` | `app` |
|
||
| `POSTGRES_USER` | `user_ZPKMQ6` |
|
||
| `POSTGRES_PASSWORD` | `password_CYmsGt` |
|
||
| `SENTRY_DSN` | *(留空)* |
|
||
| `DOCKER_IMAGE_BACKEND` | `backend` |
|
||
| `DOCKER_IMAGE_FRONTEND` | `frontend` |
|
||
|
||
### 8.6 启用 Gitea Actions
|
||
|
||
1. 进入仓库 → **Settings** → **Repository**
|
||
2. 确保 **Actions** 功能已启用
|
||
3. 如果 Gitea 全局未启用 Actions,需要在 Gitea 配置文件中添加:
|
||
|
||
```ini
|
||
; 在 /opt/1panel/apps/gitea/gitea/data/gitea/conf/app.ini 中
|
||
[actions]
|
||
ENABLED = true
|
||
```
|
||
|
||
修改后重启 Gitea 容器:
|
||
|
||
```bash
|
||
docker restart 1Panel-gitea-FSXv
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 验证部署
|
||
|
||
### 9.1 本地访问测试
|
||
|
||
```bash
|
||
# 后端健康检查
|
||
curl http://127.0.0.1:8000/api/v1/utils/health-check/
|
||
|
||
# 前端页面
|
||
curl -I http://127.0.0.1:3001
|
||
```
|
||
|
||
### 9.2 域名访问测试
|
||
|
||
```bash
|
||
# 前端
|
||
curl -I https://makefire.fun
|
||
|
||
# 后端 API 文档
|
||
curl -I https://api.makefire.fun/docs
|
||
|
||
# 后端健康检查
|
||
curl https://api.makefire.fun/api/v1/utils/health-check/
|
||
```
|
||
|
||
### 9.3 CI/CD 测试
|
||
|
||
```bash
|
||
# 在本地开发机上
|
||
cd /Users/weifeng/Workspace/full-stack-fastapi-template
|
||
echo "# test" >> README.md
|
||
git add .
|
||
git commit -m "test: trigger CI/CD"
|
||
git push gitea main
|
||
```
|
||
|
||
然后在 Gitea 仓库的 **Actions** 标签中查看运行状态。
|
||
|
||
---
|
||
|
||
## 10. 日常运维
|
||
|
||
### 查看日志
|
||
|
||
```bash
|
||
cd /opt/fastapi-app
|
||
docker compose -f compose.prod.yml logs -f backend # 后端日志
|
||
docker compose -f compose.prod.yml logs -f frontend # 前端日志
|
||
docker compose -f compose.prod.yml logs -f # 全部日志
|
||
```
|
||
|
||
### 重启服务
|
||
|
||
```bash
|
||
docker compose -f compose.prod.yml restart backend
|
||
docker compose -f compose.prod.yml restart frontend
|
||
```
|
||
|
||
### 手动重新部署
|
||
|
||
```bash
|
||
cd /opt/fastapi-app
|
||
git pull origin main
|
||
docker compose -f compose.prod.yml build
|
||
docker compose -f compose.prod.yml down
|
||
docker compose -f compose.prod.yml up -d
|
||
```
|
||
|
||
### 清理 Docker 资源
|
||
|
||
```bash
|
||
# 清理无用镜像(释放磁盘空间)
|
||
docker image prune -f
|
||
docker system prune -f
|
||
```
|
||
|
||
### 数据库备份
|
||
|
||
```bash
|
||
# 备份
|
||
docker exec 1Panel-postgresql-bxrK pg_dump -U user_ZPKMQ6 app > backup_$(date +%Y%m%d).sql
|
||
|
||
# 恢复
|
||
docker exec -i 1Panel-postgresql-bxrK psql -U user_ZPKMQ6 app < backup_20260311.sql
|
||
```
|