Files
secondary-school-grade-archive/docs/DEPLOY.md
T
dekun e329d3398a Initial commit: secondary school grade archive system.
Add FastAPI/React app with Docker deployment, Ubuntu one-click install, and docs for junior/senior high score tracking and mistake bank.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-28 11:18:58 +08:00

305 lines
8.2 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.
# Ubuntu 部署文档
> **中学成绩档案系统**Secondary School Grade Archive
> 版权所有 © 马建军 · 微信 **dekun03** · 手机 **18364911125**
> 代码仓库:[https://git.bz121.com/dekun/secondary-school-grade-archive.git](https://git.bz121.com/dekun/secondary-school-grade-archive.git)
---
## 1. 部署概述
| 项目 | 说明 |
|------|------|
| 目标系统 | Ubuntu 20.04 / 22.04 / 24.04(推荐 22.04+ |
| 运行用户 | **root**(一键脚本要求) |
| 安装目录 | **`/opt/secondary-school-grade-archive`** |
| 部署方式 | Docker Compose |
| 对外端口 | **`23566`**HTTP,可在 `.env` 修改 `WEB_PORT` |
| 反向代理 | **不包含在本项目中**,需用户自行配置 Nginx/Caddy 等 |
### 1.1 架构说明
```
浏览器 ──► :23566 (Nginx/Web) ──► API (内部) ──► PostgreSQL (内部)
└──► Ollama (宿主机,可选)
└──► uploads/ (宿主机挂载)
```
- **Web**:Nginx 提供前端静态文件,并将 `/api` 反向代理到后端容器
- **API**FastAPI,不直接暴露端口到宿主机
- **PostgreSQL**:仅 Docker 内网访问,不映射宿主机端口
- **Ollama**:可选,运行在宿主机,容器通过 `host.docker.internal` 访问
---
## 2. 环境要求
### 2.1 硬件(建议)
| 资源 | 最低 | 推荐 |
|------|------|------|
| CPU | 2 核 | 4 核+ |
| 内存 | 2 GB | 4 GB+(启用 OCR 建议 8 GB |
| 磁盘 | 10 GB | 20 GB+ |
### 2.2 软件
- Ubuntu Server64 位)
- 可访问互联网(拉取 Docker 镜像与 Git 仓库)
- 防火墙放行 **23566/TCP**(若需外网访问)
### 2.3 端口
| 端口 | 用途 | 是否必须对外开放 |
|------|------|------------------|
| **23566** | Web 前端 + API(经 Nginx 统一入口) | 是 |
| 11434 | Ollama(宿主机,错题 AI 解法) | 仅本机,可不对外 |
| 5432 | PostgreSQL | **否**(已关闭对外映射) |
---
## 3. 一键部署(推荐)
**root** 登录 Ubuntu 服务器后执行:
```bash
# 方式 A:克隆后执行(仓库已有代码时)
git clone https://git.bz121.com/dekun/secondary-school-grade-archive.git /opt/secondary-school-grade-archive
cd /opt/secondary-school-grade-archive
chmod +x deploy/*.sh
bash deploy/install.sh
```
```bash
# 方式 B:仅下载安装脚本(仓库已推送 install.sh 后)
export WEB_PORT=23566
export INSTALL_DIR=/opt/secondary-school-grade-archive
curl -fsSL https://git.bz121.com/dekun/secondary-school-grade-archive/raw/branch/main/deploy/install.sh -o /tmp/install.sh
chmod +x /tmp/install.sh
bash /tmp/install.sh
```
### 3.1 脚本自动完成的事项
1. 检测是否为 root 用户
2. 检测 Ubuntu/Debian 系操作系统
3. 检测内存、磁盘(不足时警告)
4. 检测 **23566** 端口是否占用
5. 安装 `git``curl``openssl` 等基础工具
6. 若未安装 Docker,自动安装 **Docker CE + Compose 插件**
7. 克隆/更新代码到 `/opt/secondary-school-grade-archive`
8. 自动生成 `.env`(随机 `SECRET_KEY`、数据库密码)
9. `docker compose up -d --build` 构建并启动
10. 等待 API 健康检查通过后输出访问地址
### 3.2 部署成功后的访问
```
http://<服务器IP>:23566
```
首次使用请在页面 **注册** 账号,然后登录添加学生。
---
## 4. 环境变量(`.env`
部署后配置文件位于:
```
/opt/secondary-school-grade-archive/.env
```
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `WEB_PORT` | `23566` | Web 对外端口 |
| `SECRET_KEY` | 自动生成 | JWT 密钥,生产环境请勿泄露 |
| `POSTGRES_PASSWORD` | 自动生成 | 数据库密码 |
| `CORS_ORIGINS` | 含服务器 IP | 前端跨域白名单 |
| `OLLAMA_BASE_URL` | `http://host.docker.internal:11434` | Ollama 地址 |
| `OLLAMA_MODEL` | `qwen2.5:7b` | 模型名称 |
| `FLUCTUATION_THRESHOLD` | `0.08` | 成绩波动高亮阈值(8% |
修改 `.env` 后重启:
```bash
cd /opt/secondary-school-grade-archive
docker compose --env-file .env up -d
```
修改 `WEB_PORT` 后需重新创建容器:
```bash
docker compose --env-file .env up -d --force-recreate web
```
---
## 5. 常用运维命令
```bash
cd /opt/secondary-school-grade-archive
# 查看运行状态
docker compose ps
# 查看日志
docker compose logs -f
docker compose logs -f api
docker compose logs -f web
# 停止服务
docker compose down
# 启动服务
docker compose --env-file .env up -d
# 更新版本(拉代码 + 重建)
bash deploy/update.sh
# 数据备份
bash deploy/backup.sh
# 卸载容器(保留数据)
bash deploy/uninstall.sh
# 卸载并删除数据库卷(危险)
REMOVE_VOLUMES=1 bash deploy/uninstall.sh
```
---
## 6. Ollama 可选配置(错题 AI 解法)
错题上传后的「整理题目 / 生成解法」依赖宿主机 Ollama。若不安装,OCR 仍可用,AI 解法需手动填写。
```bash
# 安装 Ollama(参考 https://ollama.com
curl -fsSL https://ollama.com/install.sh | sh
# 拉取模型
ollama pull qwen2.5:7b
# 确认服务运行
curl http://127.0.0.1:11434/api/tags
```
确保 `.env` 中:
```
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_MODEL=qwen2.5:7b
```
---
## 7. 反向代理(用户自行配置)
**本项目不包含 HTTPS、域名、反向代理配置。** 若需通过域名访问或启用 HTTPS,请在宿主机自行配置 Nginx/Caddy/Traefik 等。
### 7.1 原则
- 反向代理将流量转发到 **`http://127.0.0.1:23566`**
- 代理需支持 **WebSocket**(若未来扩展)及 **大文件上传**(错题图片最大 10MB
- 代理 `/api``/` 均应转发到同一 upstream(本项目 Nginx 已统一处理)
### 7.2 Nginx 示例(仅供参考,不包含在项目中)
```nginx
server {
listen 443 ssl http2;
server_name grade.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
client_max_body_size 10M;
location / {
proxy_pass http://127.0.0.1:23566;
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;
}
}
```
使用 HTTPS 反向代理后,请同步修改 `.env` 中的 `CORS_ORIGINS`,加入 `https://grade.example.com`
---
## 8. 防火墙示例(UFW
```bash
ufw allow 22/tcp
ufw allow 23566/tcp
ufw enable
```
---
## 9. 故障排查
| 现象 | 处理 |
|------|------|
| 无法访问 23566 | `docker compose ps` 确认 web 运行;`ufw status` 检查防火墙 |
| 注册/登录 502 | `docker compose logs api` 查看后端;确认 db 健康 |
| OCR 很慢/失败 | 首次运行需下载 PaddleOCR 模型;查看 api 日志 |
| AI 解法失败 | 确认宿主机 Ollama 运行;`curl host.docker.internal:11434` 从 api 容器内测试 |
| 端口被占用 | 修改 `.env``WEB_PORT` 或释放占用进程 |
进入 API 容器调试:
```bash
docker compose exec api bash
```
---
## 10. 数据备份与恢复
### 备份
```bash
bash /opt/secondary-school-grade-archive/deploy/backup.sh
```
生成文件位于 `backups/`
- `db_YYYYMMDD_HHMMSS.sql` — 数据库
- `uploads_YYYYMMDD_HHMMSS.tar.gz` — 错题图片
### 恢复数据库(示例)
```bash
cd /opt/secondary-school-grade-archive
docker compose exec -T db psql -U postgres student_archive < backups/db_XXXXXX.sql
```
---
## 11. 版权与授权
本软件著作权归 **马建军** 所有。部署和使用须遵守 [LICENSE](../LICENSE) 与 [COPYRIGHT.md](../COPYRIGHT.md)。
- 微信:**dekun03**
- 手机:**18364911125**
未经授权不得用于商业分发或去除版权信息。
---
## 12. 自定义安装参数
```bash
# 自定义端口
WEB_PORT=23566 bash deploy/install.sh
# 自定义目录
INSTALL_DIR=/opt/my-grade-app bash deploy/install.sh
# 指定分支
BRANCH=main bash deploy/install.sh
```