10 KiB
10 KiB
钢琴练习方案系统 - 部署 SOP
版本:v1.3 日期:2026-04-24 核心原则:不删除,只备份后新增/替换
一、部署原则(铁律)
| 操作 | 允许? | 说明 |
|---|---|---|
| 删除容器 | ❌ 禁止 | 停止即可,容器配置是资产 |
| 删除 volume | ❌ 禁止 | 数据资产,不可恢复 |
| 删除 host 文件 | ❌ 禁止 | 先备份到 /tmp/backup_YYYYMMDD/ |
| 覆盖文件 | ⚠️ 先备份 | 任何覆盖操作前必须先备份 |
| 停止容器 | ✅ 允许 | stop 是安全的 |
| 启动新容器 | ✅ 允许 | 配合正确的挂载配置 |
脚本优先原则(铁律)
使脚本执行失败时:修复脚本,而非绕过脚本。
| 错误行为 | 正确行为 |
|---|---|
脚本报错 → docker rm 手动清理 |
脚本报错 → 查看日志 → 修复脚本问题 → 重跑脚本 |
| 挂载丢失 → 手动指定新挂载 | 挂载丢失 → 更新脚本的挂载配置 → 重跑脚本 |
镜像加载失败 → docker rmi 清理 |
镜像加载失败 → 检查错误 → 重跑脚本 |
容器启动失败 → docker rm 重来 |
容器启动失败 → 查看 docker logs → 修复配置 → 重跑脚本 |
一旦开始用脚本部署,就要坚持用到底,中途放弃脚本去做手动操作,等于打开了破坏系统的潘多拉魔盒。
二、部署前检查清单
[ ] 确认本地代码已验证通过
[ ] 确认无未提交的代码
[ ] 确认获得用户的明确同意(用户说"部署吧"或"可以部署")
[ ] 确认需要保留的挂载点列表(见下方)
[ ] 确认 Docker Desktop 已启动(Windows)
必须保留的挂载点
| 类型 | 源 | 容器内 | 说明 |
|---|---|---|---|
| Volume | piano-plan-data |
/app/data |
SQLite 数据库 |
| Volume | piano-plan-output |
/app/output |
PDF 输出 |
| Bind Mount | /opt/piano-plan/config |
/app/config |
API 配置 |
三、本地发布包准备
3.1 版本目录结构
每个版本发布前,在本地 releases/ 目录下创建:
releases/
└── v1.3.0/
├── bk/ # 上次生产环境备份(来自服务器)
│ ├── piano_plans.db # 上次生产数据库
│ ├── docker/ # 上次版本的 docker 镜像 tar
│ │ └── piano-plan.tar
│ └── config/ # 上次版本的配置备份
│ └── api_config.json
└── toRelease/ # 本次发布文件
├── program/ # 本次发布的程序包
│ └── piano-plan.tar
├── schema.sql # 数据库 schema(仅结构,不含数据)
├── scripts/ # 发布脚本
│ └── deploy.sh
└── config/ # 本次配置(如有变更)
└── api_config.json
3.2 生成 schema.sql(仅结构)
cd "D:\F\NewI\opencode\daily-workspace\projects\青年钢琴集体课\练习方案系统"
# 进入版本目录
mkdir -p releases/v1.3.0/toRelease/scripts
# 导出数据库结构(不含数据)
docker exec piano-plan-for-export sqlite3 /app/data/piano_plans.db ".schema" > releases/v1.3.0/toRelease/schema.sql
# 或使用 python
python -c "
import sqlite3
conn = sqlite3.connect('data/piano_plans.db')
with open('releases/v1.3.0/toRelease/schema.sql', 'w', encoding='utf-8') as f:
for line in conn.iterdump():
if 'CREATE' in line or 'CREATE' in line.upper():
f.write(line + '\n')
"
3.3 构建 Docker 镜像并打包
cd "D:\F\NewI\opencode\daily-workspace\projects\青年钢琴集体课\练习方案系统"
# 1. 构建镜像
docker build -t piano-plan:v1.3.0 .
# 2. 保存镜像
docker save piano-plan:v1.3.0 -o releases/v1.3.0/toRelease/program/piano-plan.tar
四、服务器部署步骤
4.1 SSH 到服务器
ssh -i ~/.ssh/id_rsa root@47.106.65.108
4.2 创建版本目录并备份上次生产环境
# 创建版本目录
mkdir -p /opt/piano-plan/releases/v1.3.0/bk
mkdir -p /opt/piano-plan/releases/v1.3.0/toRelease
# 备份当前生产环境到 bk/
# 1. 备份数据库
docker cp piano-plan:/app/data/piano_plans.db /opt/piano-plan/releases/v1.3.0/bk/piano_plans.db.$(date +%Y%m%d)
# 2. 备份 docker 镜像(如果存在)
docker save piano-plan:$(docker inspect piano-plan --format '{{.Config.Image}}' | sed 's/piano-plan://') -o /opt/piano-plan/releases/v1.3.0/bk/docker/piano-plan.tar 2>/dev/null || true
# 3. 备份配置
cp -r /opt/piano-plan/config /opt/piano-plan/releases/v1.3.0/bk/config.bak.$(date +%Y%m%d)
4.3 上传本次发布文件
# 在本地执行上传
exit # 先退出服务器 SSH
# 上传发布包
scp -i ~/.ssh/id_rsa -r releases/v1.3.0/toRelease/* root@47.106.65.108:/opt/piano-plan/releases/v1.3.0/toRelease/
4.4 服务器执行部署
# SSH 再次连接
ssh -i ~/.ssh/id_rsa root@47.106.65.108
cd /opt/piano-plan/releases/v1.3.0
# 1. 停止旧容器
docker stop piano-plan
docker rm piano-plan
# 2. 加载新镜像
docker load -i toRelease/program/piano-plan.tar
# 3. 执行数据库迁移(仅 schema,不覆盖数据)
# 方法A:使用 sqlite3 直接执行 schema(如果有 ALTER TABLE 新增字段)
docker cp toRelease/schema.sql piano-plan:/tmp/schema.sql
docker exec piano-plan sqlite3 /app/data/piano_plans.db < /tmp/schema.sql
# 方法B:如果 schema 变更较大,先备份再重建表结构(不丢失数据)
# 具体看本次变更内容决定
# 4. 启动新容器
docker run -d \
--name piano-plan \
-p 5001:5001 \
--restart unless-stopped \
-e FLASK_ENV=production \
-v piano-plan-data:/app/data \
-v piano-plan-output:/app/output \
-v /opt/piano-plan/config:/app/config \
piano-plan:v1.3.0
4.5 验证
# 检查容器状态
docker ps --filter name=piano-plan
# 检查日志
docker logs piano-plan --tail 30
# 验证数据库表结构
docker exec piano-plan sqlite3 /app/data/piano_plans.db ".tables"
# 验证服务
curl -I http://localhost:5001/
五、数据保护规范
5.1 必须保护的数据(绝对不删除)
| 数据类型 | 存储位置 | 说明 |
|---|---|---|
| 用户数据 | piano-plan-data:/app/data | users 表 |
| 学员数据 | piano-plan-data:/app/data | students, student_problems 表 |
| 班级数据 | piano-plan-data:/app/data | classes 表 |
| 练习方案 | piano-plan-data:/app/data | practice_plans 表 |
| 目标数据 | piano-plan-data:/app/data | goals, goal_relations, student_goals 表 |
| 问题数据 | piano-plan-data:/app/data | problems 表 |
5.2 本次发布 schema 变更
本次发布涉及新增目标管理模块,需要执行数据库迁移:
- 新增
goals表- 新增
goal_relations表- 新增
student_goals表- 修改
problems表:更新分类体系- 修改
students表:无变更
5.3 双备份保障
| 备份位置 | 内容 | 说明 |
|---|---|---|
/opt/piano-plan/releases/v1.3.0/bk/ |
上次生产环境完整备份 | 版本回退用 |
/opt/piano-plan/releases/v1.3.1/bk/ |
本次发布前备份 | 下次发布时自动创建 |
六、回滚流程
6.1 回滚到上一版本
# 停止当前容器
docker stop piano-plan
docker rm piano-plan
# 使用 bk 中的旧镜像(如果有)
docker load -i /opt/piano-plan/releases/v1.3.0/bk/docker/piano-plan.tar
# 启动旧容器
docker run -d \
--name piano-plan \
-p 5001:5001 \
--restart unless-stopped \
-e FLASK_ENV=production \
-v piano-plan-data:/app/data \
-v piano-plan-output:/app/output \
-v /opt/piano-plan/config:/app/config \
piano-plan:旧版本标签
6.2 数据库紧急回滚
# 停止容器
docker stop piano-plan
# 从 bk 恢复数据库
cp /opt/piano-plan/releases/v1.3.0/bk/piano_plans.db.上次的日期 piano-plan:/app/data/piano_plans.db
# 重启
docker start piano-plan
七、服务信息
| 项目 | 值 |
|---|---|
| 生产地址 | https://piano.yoin.fun |
| SSH | ssh -i ~/.ssh/id_rsa root@47.106.65.108 |
| 容器名 | piano-plan |
| 端口 | 5001 |
| 数据库位置 | piano-plan-data volume |
| API配置位置 | /opt/piano-plan/config |
| 发布包位置 | /opt/piano-plan/releases/ |
Volume 列表
| Volume | 容器内路径 | 说明 |
|---|---|---|
| piano-plan-data | /app/data | SQLite 数据库 |
| piano-plan-output | /app/output | PDF 导出 |
Bind Mount 列表
| 源 | 容器内路径 | 说明 |
|---|---|---|
| /opt/piano-plan/config | /app/config | API 配置 |
八、API 配置说明
8.1 支持的 Provider
| Provider | Endpoint | 模型 |
|---|---|---|
| minimax | https://api.minimaxi.com/anthropic/v1 | MiniMax-M2.7-highspeed |
| volcengine | https://ark.cn-beijing.volces.com/api/coding/v3 | doubao-seed-2.0-pro |
| deepseek | https://api.deepseek.com | deepseek-chat |
8.2 API 配置存储
- 配置存储在
/opt/piano-plan/config/api_config.json - 每个 provider 的 key 存储在
api_keys映射中 - 切换 provider 时自动使用对应的 key
九、常见问题
Q: 数据库 schema 迁移失败?
A: 检查 sqlite3 版本兼容性,确保 .schema 导出的 SQL 兼容目标数据库版本
Q: 容器无法启动?
A: 检查日志 docker logs piano-plan,常见原因:端口被占用、volume 权限问题
Q: 目标管理功能报错?
A: 检查数据库是否成功执行了 schema 迁移,新增了 goals, goal_relations, student_goals 表
Q: SSE 不完整?
A: nginx 需要为 SSE 配置特定的代理设置,参考之前文档
十、检查清单(部署完成后必填)
[ ] 容器状态:running
[ ] 服务响应:HTTP 200/302
[ ] 数据库表完整:users, students, classes, student_problems, practice_plans, problems, goals, goal_relations, student_goals
[ ] 目标管理功能正常:创建目标、分配目标、评估目标
[ ] API 配置正确
[ ] 功能验证:能生成练习方案
十一、版本历史
| 版本 | 日期 | 变更 |
|---|---|---|
| v1.3 | 2026-04-24 | 目标管理模块:Goal/GoalRelation/StudentGoal;问题分类重构;学习历程时间线 |
| v1.2 | 2026-04-23 | 问题迁移到数据库;移除个性化方案挂载 |
| v1.1 | 2026-04-20 | 模板管理;API配置界面 |
| v1.0 | 2026-04-17 | 初始版本 |
最后更新:2026-04-24 更新原因:v1.3 目标管理模块发布;新增版本目录结构和双备份规范;schema 发布说明