优化证书生成与正式部署配置
This commit is contained in:
783
docs/正式部署操作手册.md
Normal file
783
docs/正式部署操作手册.md
Normal file
@@ -0,0 +1,783 @@
|
||||
# 证书系统正式部署操作手册
|
||||
|
||||
本文档用于把“培训结业证书管理与查询系统”部署到正式服务器,并完成短信验证码配置、上线验收、日常运维和回滚准备。
|
||||
|
||||
适用范围:
|
||||
|
||||
- 正式工程:`backend/`、`frontend/`、`docker-compose.yml`
|
||||
- 不适用于本地验收版:`local_app/`
|
||||
|
||||
## 1. 部署架构
|
||||
|
||||
推荐一期使用单机 Docker Compose:
|
||||
|
||||
```text
|
||||
用户浏览器
|
||||
-> 域名 HTTPS
|
||||
-> 宿主机 Nginx
|
||||
-> frontend 容器,端口 8080,内置 Nginx,负责前端页面和 /api 代理
|
||||
-> backend 容器,端口 8000,FastAPI
|
||||
-> MySQL 8,Compose 内置 MySQL 或阿里云 RDS MySQL
|
||||
```
|
||||
|
||||
正式环境不要直接运行:
|
||||
|
||||
```bash
|
||||
python local_app/server.py
|
||||
```
|
||||
|
||||
正式环境只运行:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## 2. 服务器准备
|
||||
|
||||
建议配置:
|
||||
|
||||
- 操作系统:Ubuntu 22.04 LTS 或同类 Linux。
|
||||
- 规格:2 核 4G 起步。
|
||||
- 磁盘:建议至少 40G,最好把 `/data` 放到数据盘。
|
||||
- 域名:已解析到服务器公网 IP。
|
||||
- HTTPS 证书:已准备好证书文件。
|
||||
|
||||
安装 Docker:
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt install -y docker.io docker-compose-plugin
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
创建数据目录:
|
||||
|
||||
```bash
|
||||
mkdir -p /data/certificate-system/uploads
|
||||
mkdir -p /data/certificate-system/error-reports
|
||||
mkdir -p /data/certificate-system/exports
|
||||
mkdir -p /data/certificate-system/pdf-cache
|
||||
mkdir -p /data/backups/mysql
|
||||
```
|
||||
|
||||
## 3. 上传代码
|
||||
|
||||
推荐目录:
|
||||
|
||||
```text
|
||||
/opt/certificate-system
|
||||
```
|
||||
|
||||
如果用 Git:
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
git clone <你的仓库地址> certificate-system
|
||||
cd /opt/certificate-system
|
||||
```
|
||||
|
||||
如果手动上传压缩包:
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
unzip certificate-system.zip
|
||||
cd /opt/certificate-system
|
||||
```
|
||||
|
||||
## 4. 配置 .env
|
||||
|
||||
Docker Compose 使用项目根目录的 `.env`,不是 `backend/.env`。
|
||||
|
||||
```bash
|
||||
cd /opt/certificate-system
|
||||
cp .env.example .env
|
||||
vim .env
|
||||
```
|
||||
|
||||
### 4.1 使用 Compose 内置 MySQL
|
||||
|
||||
`.env` 示例:
|
||||
|
||||
```env
|
||||
APP_ENV=production
|
||||
DATABASE_URL=mysql+pymysql://certificate:请改成业务库强密码@mysql:3306/certificate_system
|
||||
SECRET_KEY=请改成至少32字节随机字符串
|
||||
PUBLIC_BASE_URL=https://你的域名
|
||||
CERTIFICATE_NO_SECRET=请改成另一串随机字符串
|
||||
PDF_CACHE_DAYS=30
|
||||
PDF_CLEANUP_DAYS=5
|
||||
DATA_ROOT=/data/certificate-system
|
||||
CORS_ORIGINS=https://你的域名
|
||||
|
||||
SMS_MODE=local
|
||||
ALIYUN_ACCESS_KEY_ID=
|
||||
ALIYUN_ACCESS_KEY_SECRET=
|
||||
ALIYUN_SMS_SIGN_NAME=
|
||||
ALIYUN_SMS_TEMPLATE_CODE=
|
||||
```
|
||||
|
||||
生成随机密钥:
|
||||
|
||||
```bash
|
||||
openssl rand -hex 32
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
同时修改 `docker-compose.yml` 里的 MySQL 密码,保证和 `DATABASE_URL` 一致:
|
||||
|
||||
```yaml
|
||||
MYSQL_ROOT_PASSWORD: 请改成root强密码
|
||||
MYSQL_DATABASE: certificate_system
|
||||
MYSQL_USER: certificate
|
||||
MYSQL_PASSWORD: 请改成业务库强密码
|
||||
```
|
||||
|
||||
### 4.2 使用阿里云 RDS MySQL
|
||||
|
||||
`.env` 示例:
|
||||
|
||||
```env
|
||||
APP_ENV=production
|
||||
DATABASE_URL=mysql+pymysql://RDS账号:RDS密码@RDS内网地址:3306/certificate_system
|
||||
SECRET_KEY=请改成至少32字节随机字符串
|
||||
PUBLIC_BASE_URL=https://你的域名
|
||||
CERTIFICATE_NO_SECRET=请改成另一串随机字符串
|
||||
PDF_CACHE_DAYS=30
|
||||
PDF_CLEANUP_DAYS=5
|
||||
DATA_ROOT=/data/certificate-system
|
||||
CORS_ORIGINS=https://你的域名
|
||||
|
||||
SMS_MODE=local
|
||||
ALIYUN_ACCESS_KEY_ID=
|
||||
ALIYUN_ACCESS_KEY_SECRET=
|
||||
ALIYUN_SMS_SIGN_NAME=
|
||||
ALIYUN_SMS_TEMPLATE_CODE=
|
||||
```
|
||||
|
||||
RDS 检查点:
|
||||
|
||||
- ECS 和 RDS 在同一个 VPC。
|
||||
- RDS 白名单加入 ECS 内网 IP。
|
||||
- RDS 中已创建数据库 `certificate_system`。
|
||||
- 不建议开放 RDS 公网访问。
|
||||
|
||||
如果使用 RDS,可以保留 `docker-compose.yml` 里的 `mysql` 服务但不使用;更干净的做法是拆一个生产 compose 文件去掉 `mysql`,一期也可以先保持现状,只要 `DATABASE_URL` 指向 RDS,业务后端就不会连接 Compose 内置 MySQL。
|
||||
|
||||
## 5. 短信验证码配置
|
||||
|
||||
系统支持两种短信模式:
|
||||
|
||||
```env
|
||||
SMS_MODE=local
|
||||
```
|
||||
|
||||
本地测试模式。验证码会打印在后端日志里,不会真的发短信。
|
||||
|
||||
```env
|
||||
SMS_MODE=aliyun
|
||||
```
|
||||
|
||||
阿里云短信模式。系统会调用阿里云短信服务发送验证码。
|
||||
|
||||
### 5.1 开通阿里云短信服务
|
||||
|
||||
在阿里云控制台操作:
|
||||
|
||||
1. 登录阿里云控制台。
|
||||
2. 搜索“短信服务”,开通短信服务。
|
||||
3. 进入“国内消息”。
|
||||
4. 申请短信签名。
|
||||
5. 申请短信模板。
|
||||
6. 创建 RAM 用户或 RAM 角色,并授予短信服务发送权限。
|
||||
7. 创建 AccessKey,保存 `AccessKey ID` 和 `AccessKey Secret`。
|
||||
|
||||
安全建议:
|
||||
|
||||
- 不要使用主账号 AccessKey。
|
||||
- 使用 RAM 用户,权限只给短信服务需要的最小权限。
|
||||
- AccessKey Secret 只会显示一次,要保存到密码管理工具或服务器安全配置中。
|
||||
|
||||
### 5.2 申请短信签名
|
||||
|
||||
签名是短信开头的 `【xxx】`。
|
||||
|
||||
建议填写:
|
||||
|
||||
```text
|
||||
签名名称:与你公司/品牌/备案主体一致,例如 慧愈文化
|
||||
适用场景:验证码
|
||||
签名来源:企事业单位全称或简称
|
||||
申请说明:用于学员查询培训结业证书时进行手机号验证码验证
|
||||
```
|
||||
|
||||
审核通过后,把签名名称填到:
|
||||
|
||||
```env
|
||||
ALIYUN_SMS_SIGN_NAME=审核通过的签名名称
|
||||
```
|
||||
|
||||
注意:这里不要写方括号,例如写 `慧愈文化`,不要写 `【慧愈文化】`。
|
||||
|
||||
### 5.3 申请短信模板
|
||||
|
||||
当前代码发送的模板变量是:
|
||||
|
||||
```json
|
||||
{"code":"123456"}
|
||||
```
|
||||
|
||||
所以阿里云模板必须包含变量:
|
||||
|
||||
```text
|
||||
${code}
|
||||
```
|
||||
|
||||
推荐模板内容:
|
||||
|
||||
```text
|
||||
您的验证码是${code},5分钟内有效,请勿泄露给他人。
|
||||
```
|
||||
|
||||
审核通过后,拿到模板 Code,例如:
|
||||
|
||||
```text
|
||||
SMS_123456789
|
||||
```
|
||||
|
||||
填到:
|
||||
|
||||
```env
|
||||
ALIYUN_SMS_TEMPLATE_CODE=SMS_123456789
|
||||
```
|
||||
|
||||
### 5.4 配置生产 .env
|
||||
|
||||
正式发短信时,将 `.env` 改成:
|
||||
|
||||
```env
|
||||
SMS_MODE=aliyun
|
||||
ALIYUN_ACCESS_KEY_ID=你的AccessKeyID
|
||||
ALIYUN_ACCESS_KEY_SECRET=你的AccessKeySecret
|
||||
ALIYUN_SMS_SIGN_NAME=你的短信签名
|
||||
ALIYUN_SMS_TEMPLATE_CODE=你的短信模板Code
|
||||
```
|
||||
|
||||
配置完成后必须重建后端镜像,因为阿里云 SDK 是后端依赖:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build backend
|
||||
docker compose restart frontend
|
||||
```
|
||||
|
||||
或者整体重建:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### 5.5 验证短信配置
|
||||
|
||||
先看配置是否进入容器:
|
||||
|
||||
```bash
|
||||
docker compose exec backend env | grep -E "SMS_MODE|ALIYUN"
|
||||
```
|
||||
|
||||
直接从后端容器发一条测试短信到自己的手机号:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python - <<'PY'
|
||||
from app.services.sms import send_sms
|
||||
|
||||
phone = "请改成你的手机号"
|
||||
ok = send_sms(phone, "123456")
|
||||
print("send result:", ok)
|
||||
PY
|
||||
```
|
||||
|
||||
再看日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend | grep -E "阿里云短信|短信验证码|未安装依赖"
|
||||
```
|
||||
|
||||
成功时通常能看到:
|
||||
|
||||
```text
|
||||
[阿里云短信] 发送成功: 138xxxx0000
|
||||
```
|
||||
|
||||
然后做完整业务验证:
|
||||
|
||||
1. 打开 `https://你的域名/query`。
|
||||
2. 切到“短信验证码查询”。
|
||||
3. 输入测试手机号。
|
||||
4. 获取验证码。
|
||||
5. 输入短信验证码。
|
||||
6. 查询证书。
|
||||
|
||||
### 5.6 短信常见问题
|
||||
|
||||
如果日志出现:
|
||||
|
||||
```text
|
||||
未安装依赖
|
||||
```
|
||||
|
||||
说明镜像里没有安装阿里云 SDK。确认 `backend/requirements.txt` 包含:
|
||||
|
||||
```text
|
||||
alibabacloud-dysmsapi20170525==4.5.1
|
||||
```
|
||||
|
||||
然后执行:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build backend
|
||||
```
|
||||
|
||||
如果发送失败,优先检查:
|
||||
|
||||
- `SMS_MODE` 是否等于 `aliyun`。
|
||||
- `ALIYUN_ACCESS_KEY_ID` 是否正确。
|
||||
- `ALIYUN_ACCESS_KEY_SECRET` 是否正确。
|
||||
- `ALIYUN_SMS_SIGN_NAME` 是否是审核通过的签名名称,不带 `【】`。
|
||||
- `ALIYUN_SMS_TEMPLATE_CODE` 是否是审核通过的模板 Code。
|
||||
- 模板变量是否是 `${code}`。
|
||||
- 阿里云账户是否欠费。
|
||||
- RAM 用户是否有短信发送权限。
|
||||
- 手机号是否触发阿里云风控。
|
||||
|
||||
系统自身限制:
|
||||
|
||||
- 同一 IP:每分钟最多 5 次发送短信。
|
||||
- 同一手机号:5 分钟最多 3 次发送短信。
|
||||
- 短信验证码有效期:5 分钟。
|
||||
- 当前验证码保存在后端进程内存中。单机部署没问题;如果后续扩成多个 backend 实例,需要把验证码存储迁移到 Redis 或数据库,否则不同实例之间验证码不共享。
|
||||
|
||||
## 6. 首次启动
|
||||
|
||||
在项目根目录:
|
||||
|
||||
```bash
|
||||
cd /opt/certificate-system
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
看后端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
看前端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f frontend
|
||||
```
|
||||
|
||||
## 7. 初始化数据库
|
||||
|
||||
首次部署执行:
|
||||
|
||||
```bash
|
||||
docker compose exec backend python -m app.cli init-db --admin-username admin --admin-password "请换成强密码"
|
||||
```
|
||||
|
||||
这个命令会:
|
||||
|
||||
- 执行 Alembic 数据库迁移。
|
||||
- 创建基础角色。
|
||||
- 创建默认管理员。
|
||||
- 初始化默认项目配置。
|
||||
|
||||
以后升级代码时,一般执行:
|
||||
|
||||
```bash
|
||||
docker compose exec backend alembic upgrade head
|
||||
```
|
||||
|
||||
## 8. 配置 HTTPS 和域名
|
||||
|
||||
### 8.1 临时访问
|
||||
|
||||
如果只做内部验收,可以临时访问:
|
||||
|
||||
```text
|
||||
http://服务器IP:8080/admin/login
|
||||
```
|
||||
|
||||
此时安全组需要开放 `8080`。
|
||||
|
||||
### 8.2 正式访问
|
||||
|
||||
正式建议宿主机 Nginx 负责 HTTPS,反向代理到前端容器 `127.0.0.1:8080`。
|
||||
|
||||
宿主机 Nginx 示例:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name 你的域名;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name 你的域名;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/privkey.pem;
|
||||
|
||||
client_max_body_size 20m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
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 30s;
|
||||
proxy_send_timeout 120s;
|
||||
proxy_read_timeout 120s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
检查并重载:
|
||||
|
||||
```bash
|
||||
nginx -t
|
||||
systemctl reload nginx
|
||||
```
|
||||
|
||||
安全组建议开放:
|
||||
|
||||
```text
|
||||
22 SSH,最好限制办公 IP
|
||||
80 HTTP
|
||||
443 HTTPS
|
||||
```
|
||||
|
||||
正式环境不建议公网开放:
|
||||
|
||||
```text
|
||||
3306 MySQL
|
||||
8000 后端
|
||||
8080 前端容器端口
|
||||
```
|
||||
|
||||
如果宿主机 Nginx 已经代理到 `8080`,可以在安全组关闭公网 `8080`。
|
||||
|
||||
## 9. 上线验收
|
||||
|
||||
### 9.1 后台登录
|
||||
|
||||
访问:
|
||||
|
||||
```text
|
||||
https://你的域名/admin/login
|
||||
```
|
||||
|
||||
检查:
|
||||
|
||||
- 管理员账号可以登录。
|
||||
- 默认密码已改为强密码。
|
||||
- 进入“数据概览”没有 401、403、502。
|
||||
|
||||
### 9.2 项目管理
|
||||
|
||||
检查:
|
||||
|
||||
- 能新增项目。
|
||||
- 能修改项目。
|
||||
- 能启用/停用项目。
|
||||
- 默认课程名称、阶段名称、发证单位保存后生效。
|
||||
|
||||
### 9.3 学员管理
|
||||
|
||||
检查:
|
||||
|
||||
- 能新增学员。
|
||||
- 手机号格式正确。
|
||||
- 能修改学员。
|
||||
- 能删除测试学员。
|
||||
|
||||
### 9.4 证书管理和 PDF
|
||||
|
||||
检查:
|
||||
|
||||
- 能新增证书。
|
||||
- 证书编号自动生成。
|
||||
- 能预览证书。
|
||||
- 能下载 PDF。
|
||||
- PDF 底图、姓名、日期、课程、导师、二维码清晰。
|
||||
- 作废证书后不能下载正常 PDF。
|
||||
- 重置链接后旧链接失效。
|
||||
|
||||
### 9.5 Excel 导入
|
||||
|
||||
检查模板字段:
|
||||
|
||||
```text
|
||||
姓名
|
||||
手机号
|
||||
项目代码
|
||||
发证日期
|
||||
```
|
||||
|
||||
检查:
|
||||
|
||||
- 能下载模板。
|
||||
- 能上传 Excel。
|
||||
- 错误数据能生成错误报告。
|
||||
- 校验通过后能确认导入。
|
||||
- 确认导入后能生成学员和证书。
|
||||
- 能下载导入原文件。
|
||||
|
||||
### 9.6 公开查询
|
||||
|
||||
检查:
|
||||
|
||||
- `/query` 可以打开。
|
||||
- 证书编号 + 姓名 + 图形验证码可以查询。
|
||||
- 手机号 + 短信验证码可以查询。
|
||||
- 有效证书可以下载 PDF。
|
||||
- 作废证书显示作废状态。
|
||||
- 证书直达链接 `/cert/xxx` 可以打开。
|
||||
- 二维码核验链接 `/verify/xxx` 可以打开。
|
||||
|
||||
## 10. 日常运维命令
|
||||
|
||||
查看容器:
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
查看后端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend
|
||||
```
|
||||
|
||||
查看前端日志:
|
||||
|
||||
```bash
|
||||
docker compose logs -f frontend
|
||||
```
|
||||
|
||||
重启后端:
|
||||
|
||||
```bash
|
||||
docker compose restart backend
|
||||
```
|
||||
|
||||
重启全部服务:
|
||||
|
||||
```bash
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
更新代码:
|
||||
|
||||
```bash
|
||||
cd /opt/certificate-system
|
||||
git pull
|
||||
docker compose up -d --build
|
||||
docker compose exec backend alembic upgrade head
|
||||
```
|
||||
|
||||
停止服务:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
不要随便执行:
|
||||
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
`-v` 会删除 Docker volume,可能导致 Compose 内置 MySQL 数据丢失。
|
||||
|
||||
## 11. 备份
|
||||
|
||||
### 11.1 Compose 内置 MySQL
|
||||
|
||||
手动备份:
|
||||
|
||||
```bash
|
||||
mkdir -p /data/backups/mysql
|
||||
cd /opt/certificate-system
|
||||
docker compose exec -T mysql mysqldump -ucertificate -p你的业务库密码 certificate_system > /data/backups/mysql/certificate_system_$(date +%F).sql
|
||||
```
|
||||
|
||||
定时备份:
|
||||
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
|
||||
加入:
|
||||
|
||||
```cron
|
||||
30 2 * * * cd /opt/certificate-system && docker compose exec -T mysql mysqldump -ucertificate -p你的业务库密码 certificate_system > /data/backups/mysql/certificate_system_$(date +\%F).sql
|
||||
10 3 * * * find /data/backups/mysql -name "certificate_system_*.sql" -mtime +30 -delete
|
||||
```
|
||||
|
||||
### 11.2 RDS MySQL
|
||||
|
||||
建议:
|
||||
|
||||
- 开启自动备份。
|
||||
- 上线前手动创建一次快照。
|
||||
- 大版本升级前手动创建一次快照。
|
||||
- 保留至少 7 到 30 天备份。
|
||||
|
||||
### 11.3 文件数据
|
||||
|
||||
需要备份:
|
||||
|
||||
```text
|
||||
/data/certificate-system/uploads
|
||||
/data/certificate-system/error-reports
|
||||
/data/certificate-system/exports
|
||||
```
|
||||
|
||||
可以不做长期备份:
|
||||
|
||||
```text
|
||||
/data/certificate-system/pdf-cache
|
||||
```
|
||||
|
||||
PDF 缓存可以重新生成,核心数据仍以数据库和上传原文件为准。
|
||||
|
||||
## 12. 回滚
|
||||
|
||||
上线前记录当前版本:
|
||||
|
||||
```bash
|
||||
cd /opt/certificate-system
|
||||
git rev-parse HEAD
|
||||
```
|
||||
|
||||
普通代码回滚:
|
||||
|
||||
```bash
|
||||
cd /opt/certificate-system
|
||||
git checkout 上一个稳定commit
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
如果本次上线执行过数据库迁移,先不要盲目回滚数据库。正确顺序:
|
||||
|
||||
1. 上线前先备份数据库。
|
||||
2. 如果代码回滚后仍能兼容新表结构,只回滚代码。
|
||||
3. 如果迁移破坏兼容性,从备份恢复数据库。
|
||||
|
||||
恢复 Compose MySQL 备份示例:
|
||||
|
||||
```bash
|
||||
cat /data/backups/mysql/certificate_system_YYYY-MM-DD.sql | docker compose exec -T mysql mysql -ucertificate -p你的业务库密码 certificate_system
|
||||
```
|
||||
|
||||
## 13. 常见问题排查
|
||||
|
||||
### 13.1 页面打不开
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
docker compose logs -f frontend
|
||||
```
|
||||
|
||||
检查:
|
||||
|
||||
- 前端容器是否启动。
|
||||
- 服务器安全组是否开放 80/443。
|
||||
- 域名是否解析到服务器。
|
||||
- 宿主机 Nginx 是否重载成功。
|
||||
|
||||
### 13.2 后台接口 502
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
检查:
|
||||
|
||||
- backend 容器是否启动。
|
||||
- 数据库是否连接成功。
|
||||
- `DATABASE_URL` 是否正确。
|
||||
- MySQL 密码是否和 `docker-compose.yml` 一致。
|
||||
|
||||
### 13.3 登录后 401 或 403
|
||||
|
||||
检查:
|
||||
|
||||
- `.env` 的 `SECRET_KEY` 是否重启前后变化。
|
||||
- 管理员账号是否 active。
|
||||
- 角色是否存在。
|
||||
- 是否执行过 `init-db`。
|
||||
|
||||
### 13.4 PDF 中文乱码或不清楚
|
||||
|
||||
检查:
|
||||
|
||||
- `backend/Dockerfile` 是否安装 `fonts-noto-cjk`。
|
||||
- `backend/app/assets/certificate-template.png` 是否存在。
|
||||
- 是否重建了后端镜像。
|
||||
|
||||
命令:
|
||||
|
||||
```bash
|
||||
docker compose exec backend ls -lh /app/app/assets
|
||||
docker compose up -d --build backend
|
||||
```
|
||||
|
||||
### 13.5 短信收不到
|
||||
|
||||
先确认是不是还在本地模式:
|
||||
|
||||
```bash
|
||||
docker compose exec backend env | grep SMS_MODE
|
||||
```
|
||||
|
||||
如果输出:
|
||||
|
||||
```text
|
||||
SMS_MODE=local
|
||||
```
|
||||
|
||||
说明不会真实发送短信,只会打印到日志。
|
||||
|
||||
如果是阿里云模式:
|
||||
|
||||
```bash
|
||||
docker compose logs -f backend | grep -E "阿里云短信|未安装依赖|发送失败"
|
||||
```
|
||||
|
||||
重点检查签名、模板、AccessKey、账户余额和 RAM 权限。
|
||||
|
||||
## 14. 交接清单
|
||||
|
||||
交接给运维或客户前,至少交付:
|
||||
|
||||
- 服务器 IP。
|
||||
- 域名。
|
||||
- HTTPS 证书位置。
|
||||
- 项目部署目录:`/opt/certificate-system`。
|
||||
- 数据目录:`/data/certificate-system`。
|
||||
- 数据库类型:Compose MySQL 或 RDS。
|
||||
- 数据库备份策略。
|
||||
- 管理员账号,不要明文写在文档里。
|
||||
- `.env` 变量说明,不要泄露真实密钥。
|
||||
- 阿里云短信签名名称和模板 Code。
|
||||
- 阿里云 RAM 用户权限说明。
|
||||
- 回滚版本 commit。
|
||||
Reference in New Issue
Block a user