Files
AIclinicalresearch/docs/05-部署文档/07-前端Nginx-SAE部署操作手册.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

31 KiB
Raw Blame History

前端 Nginx - SAE 部署操作手册

文档版本: v1.0
创建时间: 2025-12-23
适用范围: AIclinicalresearch 平台前端服务
部署目标: 阿里云 SAEServerless 应用引擎)
镜像仓库: 阿里云 ACR 个人版


📋 目录

  1. 前置条件检查
  2. 镜像信息确认
  3. 创建SAE应用
  4. 配置环境变量
  5. 配置健康检查
  6. 配置公网访问
  7. 部署应用
  8. 验证部署
  9. 常见问题排查
  10. 日常运维

1. 前置条件检查

部署前必须完成的准备

检查项 状态 说明
ACR镜像已推送 ☑️ 镜像地址:crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0
后端服务已部署 需要获取后端VPC内网地址格式172.17.x.x:3001
VPC网络已创建 ☑️ VPC ID: vpc-2ze055cptkew9c38w4r06
交换机已创建 ☑️ 交换机 ID: vsw-2zevacop039bxrmj6yc0c (可用区F)
安全组已创建 ☑️ 安全组 ID: sg-2zedk6fi8sgmmcwdu7tu

🔑 必需的配置信息

准备以下信息(在部署过程中需要):

# ACR 镜像信息
ACR域名专有网络: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com
命名空间: ai-clinical
镜像名称: ai-clinical_frontend-nginx
镜像版本: v1.0.0

# VPC网络信息
VPC ID: vpc-2ze055cptkew9c38w4r06
交换机ID: vsw-2zevacop039bxrmj6yc0c
安全组ID: sg-2zedk6fi8sgmmcwdu7tu

# 后端服务信息从后端SAE应用获取
后端内网地址: 待获取格式172.17.x.x
后端端口: 3001

2. 镜像信息确认

📦 ACR 镜像详情

服务类型: 个人版(免费)
命名空间: ai-clinical
仓库名称: ai-clinical_frontend-nginx

镜像完整地址(专有网络):
  crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0

镜像标签:
  - v1.0.0 (生产版本digest: 68e97e28...)
  - latest (指向最新版本)

镜像大小: 91.9 MB
构建时间: 2025-12-23

🔍 验证镜像存在

登录ACR控制台验证https://cr.console.aliyun.com/

  1. 进入【个人版】→【镜像仓库】
  2. 找到 ai-clinical_frontend-nginx
  3. 确认存在 v1.0.0 标签

3. 创建SAE应用

📍 登录SAE控制台

访问:https://sae.console.aliyun.com/

选择地域:华北2北京

🆕 创建新应用

点击【创建应用】,按以下步骤填写:

步骤1应用基本信息

应用名称: frontend-nginx-service
应用描述: AI临床研究平台 - 前端静态资源服务React SPA + Nginx
命名空间: 默认命名空间(或与后端同一命名空间)

步骤2应用部署方式

部署方式: 镜像
技术栈语言: 不限

步骤3应用实例规格

实例规格: 0.5核 1GB
  
  说明:
  - 前端Nginx占用资源极少
  - 0.5核1GB完全够用
  - 对比后端需要2核4GBPython需要2核4GB

实例数量: 2
  
  说明:
  - 最小2个实例保证高可用
  - 1个实例故障时另1个继续服务
  - 前端很少需要扩容

为什么前端只需要0.5核1GB

服务类型 推荐规格 原因
Node.js 后端 2核4GB 处理AI对话、数据库查询、业务逻辑
Python 微服务 2核4GB PDF提取是CPU密集型操作
Nginx 前端 0.5核1GB 仅提供静态文件,消耗极少

步骤4VPC网络配置

VPC: vpc-2ze055cptkew9c38w4r06 (172.17.0.0/16)

交换机: vsw-2zevacop039bxrmj6yc0c
  可用区: 华北2可用区F
  网段: 172.17.0.0/24

安全组: sg-2zedk6fi8sgmmcwdu7tu
  
  ⚠️ 重要必须与后端服务在同一VPC否则无法通信

步骤5镜像配置

镜像类型: 容器镜像服务个人版

镜像地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0
  
  ⚠️ 注意事项:
  - 使用专有网络域名(带-vpc后缀不使用公网域名
  - 完整输入镜像地址(包括命名空间和标签)
  - 不要遗漏版本号 :v1.0.0

镜像版本: v1.0.0

镜像拉取策略: 总是拉取镜像Always
  
  说明:
  - 每次部署都拉取最新镜像
  - 确保使用最新代码
  - 避免使用缓存的旧镜像

步骤6应用容器配置

容器端口: 80
  
  说明:
  - Nginx默认监听80端口
  - 与Dockerfile中的EXPOSE 80一致

协议: TCP

启动命令: 
  - 不填使用Dockerfile中的ENTRYPOINT

工作目录:
  - 不填使用Dockerfile中的WORKDIR

4. 配置环境变量

⚠️ 极其重要:后端服务地址配置

环境变量配置错误是最常见的部署失败原因!

📍 获取后端内网地址

在配置前端之前必须先获取后端的VPC内网地址

  1. 登录 SAE 控制台
  2. 进入应用列表
  3. 找到 nodejs-backend-service(你的后端应用名称)
  4. 点击进入应用详情
  5. 查看【应用访问配置】→【VPC内网访问地址】

示例格式:

172.17.0.15:3001

将IP地址和端口分别记录下来。

🔧 配置环境变量

在SAE应用配置页面找到【环境变量】配置项

# 必需配置(必填)
BACKEND_SERVICE_HOST: 172.17.0.15
  
  说明:
  - 这是后端服务的VPC内网IP地址从上一步获取
  - 不要加http://前缀
  - 不要包含端口号
  - 如果不配置,容器启动会失败并报错

# 可选配置(有默认值)
BACKEND_SERVICE_PORT: 3001
  
  说明:
  - 后端服务的端口号
  - 默认值是3001
  - 如果你的后端使用其他端口,需要修改

常见错误

错误配置 正确配置 说明
http://172.17.0.15 172.17.0.15 不要加协议前缀
172.17.0.15:3001 172.17.0.15 不要包含端口(端口单独配置)
backend-service 172.17.0.15 必须使用IP不要用主机名
localhost 172.17.0.15 不能用localhost
不配置 172.17.0.15 必须配置,否则启动失败

配置验证

配置完成后,点击【验证】,确保:

  • 变量名称拼写正确(区分大小写)
  • 变量值格式正确纯IP地址
  • 没有多余的空格

5. 配置健康检查

🏥 健康检查配置

检查方式: HTTP 请求

检查路径: /health
  
  说明:
  - Nginx配置中专门提供的健康检查端点
  - 返回纯文本 "healthy"
  - 不依赖后端服务

检查端口: 80
  说明:与容器端口一致

检查协议: HTTP
  说明不是HTTPS

超时时间: 3秒
  说明静态端点3秒足够

检查间隔: 10秒
  说明每10秒检查一次

不健康阈值: 3次
  说明连续失败3次后标记为不健康

健康阈值: 2次
  说明连续成功2次后标记为健康

初始延迟: 30秒
  说明:
  - Nginx启动很快5-10秒
  - 30秒足够镜像拉取和容器启动

🔍 健康检查原理

SAE健康检查器
    ↓ (每10秒)
curl http://容器IP:80/health
    ↓
Nginx处理 /health 请求
    ↓
返回: HTTP 200 + "healthy"
    ↓
SAE标记实例为健康 ✅

如果健康检查失败SAE会

  1. 标记实例为不健康
  2. 停止向该实例转发流量
  3. 连续失败3次后重启容器

6. 配置公网访问

🌐 访问方式选择

方案A使用SAE提供的公网地址推荐用于测试

配置方式: 
  1. 在应用配置页面找到【应用访问配置】
  2. 开启【公网访问】
  3. SAE自动分配域名

获得的访问地址:
  格式: frontend-nginx-service-xxxxx.cn-beijing.sae.aliyuncs.com
  协议: HTTPSSAE自动配置证书
  
优点:
  - ✅ 免费
  - ✅ 自动HTTPS
  - ✅ 立即可用
  
缺点:
  - ❌ 域名难记
  - ❌ 无法自定义域名
  - ❌ 证书是SAE的不是你的域名

方案B绑定自定义域名推荐用于生产

前置条件:
  - 已有自己的域名(如 app.yizheng.ai
  - 域名已备案(如果服务器在中国大陆)
  - 有SSL证书可以使用免费的Let's Encrypt

配置步骤:
  1. 在域名服务商添加CNAME解析
     app.yizheng.ai → frontend-nginx-service-xxxxx.cn-beijing.sae.aliyuncs.com
  
  2. 在SAE控制台绑定域名
     【应用访问配置】→【自定义域名】→【添加域名】
  
  3. 上传SSL证书
     【应用访问配置】→【HTTPS设置】→【上传证书】
  
  4. 启用强制HTTPS
     开启【强制HTTPS跳转】

获得的访问地址:
  https://app.yizheng.ai

优点:
  - ✅ 品牌域名
  - ✅ 用户信任度高
  - ✅ SEO友好
  
缺点:
  - ⚠️ 需要域名和证书
  - ⚠️ 需要ICP备案如果在中国

🔒 HTTPS配置生产环境必须

如果使用方案B自定义域名强烈建议配置HTTPS

证书来源选择:
  
  方案1: 使用免费的Let's Encrypt证书
    - 阿里云SSL证书服务可以申请免费证书
    - 有效期3个月需要定期更新
  
  方案2: 购买商业证书
    - 有效期1年
    - 品牌信任度更高
    - 支持更多特性

证书配置:
  1. 准备证书文件
     - 证书文件domain.crt 或 domain.pem
     - 私钥文件domain.key
  
  2. 在SAE上传证书
     【应用访问配置】→【HTTPS设置】→【上传证书】
  
  3. 启用强制HTTPS
     开启【HTTP自动跳转HTTPS】

7. 部署应用

🚀 执行部署

确认所有配置无误后:

  1. 回到应用配置页面顶部
  2. 点击【部署】按钮
  3. 确认部署信息
  4. 点击【确定】

⏱️ 部署过程约2-3分钟

1. 镜像拉取阶段 (30-60秒)
   ├─ SAE连接到ACR
   ├─ 验证镜像存在
   ├─ 下载镜像层91.9MB
   └─ 解压镜像

2. 容器启动阶段 (10-20秒)
   ├─ 创建容器
   ├─ 注入环境变量
   ├─ 执行docker-entrypoint.sh
   ├─ envsubst替换nginx.conf
   ├─ 验证Nginx配置
   └─ 启动Nginx进程

3. 健康检查阶段 (30-60秒)
   ├─ 等待30秒初始延迟
   ├─ 第1次检查 /health
   ├─ 第2次检查 /health10秒后
   └─ 标记为健康 ✅

4. 流量切换阶段 (5-10秒)
   ├─ 将新实例加入负载均衡
   ├─ 从负载均衡移除旧实例
   └─ 部署完成 ✅

📊 部署状态监控

部署过程中可以实时查看:

查看方式:
  【应用详情】→【实例列表】→【查看实例状态】

状态说明:
  - 创建中: 正在拉取镜像
  - 启动中: 正在启动容器
  - 运行中: 容器已启动,等待健康检查
  - 健康: 健康检查通过,可以接收流量 ✅
  - 不健康: 健康检查失败 ❌
  - 停止: 实例已停止

部署失败常见原因

失败阶段 错误信息 解决方法
镜像拉取 image not found 检查镜像地址是否正确,确认使用-vpc域名
镜像拉取 unauthorized 检查ACR访问权限确认SAE有拉取权限
容器启动 BACKEND_SERVICE_HOST required 检查环境变量是否配置
健康检查 connection refused 检查容器端口配置应该是80
健康检查 404 not found 检查健康检查路径(应该是/health

8. 验证部署

验证清单

部署成功后,按以下步骤验证:

步骤1查看实例状态

位置: 【应用详情】→【实例列表】

检查项:
  ☑️ 实例数量: 2个实例
  ☑️ 实例状态: 全部显示"健康"
  ☑️ 健康检查: 全部通过

步骤2查看启动日志

位置: 【应用详情】→【日志】→【实时日志】

应该看到:
============================================
Starting Frontend Nginx Service
Backend Service: 172.17.0.15:3001
Container Timezone: Asia/Shanghai
Current Time: Tue Dec 23 21:07:35 CST 2025
============================================
nginx: configuration file /etc/nginx/nginx.conf test is successful

✅ 如果看到以上日志,说明配置正确
❌ 如果看到 "BACKEND_SERVICE_HOST required",说明环境变量未配置

步骤3测试健康检查端点

# 获取公网访问地址
公网地址: https://frontend-nginx-service-xxxxx.cn-beijing.sae.aliyuncs.com

# 测试健康检查使用浏览器或curl
访问: https://frontend-nginx-service-xxxxx.cn-beijing.sae.aliyuncs.com/health

预期返回:
  Status: 200 OK
  Content: healthy

✅ 如果返回 "healthy",说明前端服务正常

步骤4测试主页访问

# 访问主页
访问: https://frontend-nginx-service-xxxxx.cn-beijing.sae.aliyuncs.com/

检查项:
  ☑️ 页面能正常加载(不是空白页)
  ☑️ 看到React应用界面
  ☑️ CSS样式正确显示
  ☑️ JavaScript正常执行

步骤5测试SPA路由

# 访问一个不存在的路径测试React Router
访问: https://frontend-nginx-service-xxxxx.cn-beijing.sae.aliyuncs.com/dashboard

预期行为:
  ✅ 不报404错误
  ✅ 返回index.html
  ✅ React Router接管路由
  ✅ 显示对应的页面组件

❌ 如果看到Nginx 404页面说明nginx.conf配置有问题

步骤6测试API代理关键

# 打开浏览器开发者工具F12→ Console标签

# 执行以下代码测试API代理
fetch('/api/v1/health')
  .then(res => res.json())
  .then(data => console.log(data))

预期结果:
  ✅ 请求成功Status 200
  ✅ 返回后端的响应数据
  ✅ 没有CORS错误

❌ 如果看到CORS错误说明反向代理配置有问题
❌ 如果看到连接失败,说明后端地址配置错误

步骤7测试静态资源缓存

# 在浏览器开发者工具 → Network标签

# 第一次访问
  ✅ index.html: 状态200Cache-Control: no-cache
  ✅ index-xxxxx.js: 状态200Cache-Control: 1年

# 刷新页面(第二次访问)
  ✅ index.html: 状态200每次都重新获取
  ✅ index-xxxxx.js: 状态200 (from disk cache)(使用缓存)

步骤8测试Gzip压缩

# 在浏览器开发者工具 → Network标签
# 点击任意JS文件

检查Response Headers:
  ✅ Content-Encoding: gzip
  ✅ 文件大小减少60-70%

示例:
  原始大小: 1.2 MB
  传输大小: 350 KB (gzip压缩后)

🎉 部署成功标志

如果以上8个步骤全部通过恭喜前端服务部署成功


9. 常见问题排查

问题1实例健康检查失败

症状:

实例状态显示"不健康"
健康检查失败

排查步骤:

1. 查看实例日志
   【应用详情】→【日志】→【实时日志】→【选择实例】
   
   如果看到:
   - "BACKEND_SERVICE_HOST required" → 环境变量未配置
   - "nginx: configuration file test failed" → nginx.conf语法错误
   - 没有日志 → 容器没有启动

2. 检查健康检查配置
   【应用配置】→【健康检查】
   
   确认:
   - 检查路径: /health不是 /
   - 检查端口: 80不是3000或其他
   - 检查协议: HTTP不是HTTPS

3. 手动测试健康检查
   在SAE Webshell中执行:
   curl http://localhost/health
   
   预期返回: healthy

解决方法:

  • 配置缺失的环境变量
  • 修正健康检查路径
  • 检查容器端口配置

问题2页面能访问但API请求失败

症状:

前端页面正常显示
调用API时报错: Network Error 或 504 Gateway Timeout

排查步骤:

1. 检查浏览器Console
   看到的错误:
   - "ERR_CONNECTION_REFUSED" → 后端服务未启动
   - "504 Gateway Timeout" → 后端响应超时
   - "502 Bad Gateway" → 后端地址错误

2. 检查环境变量配置
   【应用配置】→【环境变量】
   
   验证:
   - BACKEND_SERVICE_HOST 是否配置
   - IP地址是否正确从后端SAE应用获取
   - 不要有http://前缀
   - 不要包含端口号

3. 测试后端服务可达性
   在前端容器的Webshell中:
   curl http://172.17.0.15:3001/api/v1/health
   
   如果失败:
   - 检查后端服务是否运行
   - 检查VPC网络是否相同
   - 检查安全组规则

4. 查看Nginx错误日志
   docker logs <container_id> 2>&1 | grep error
   
   常见错误:
   - "upstream: "http://172.17.0.15:3001/..." → 后端地址正确
   - "connect() failed" → 后端不可达

解决方法:

  • 修正环境变量BACKEND_SERVICE_HOST
  • 确保前后端在同一VPC
  • 检查安全组规则允许VPC内网访问
  • 重启前端应用使配置生效

问题3刷新页面报404

症状:

访问主页正常
点击链接跳转正常
刷新页面F5→ 404 Not Found

原因:

React Router使用浏览器路由BrowserRouter刷新时Nginx需要将所有路由回退到index.html。

排查步骤:

1. 访问一个React路由
   例如: https://your-domain.com/dashboard

2. 按F5刷新页面
   
   ❌ 错误现象: 看到Nginx 404页面
   ✅ 正确现象: 页面正常显示

3. 检查nginx.conf配置
   登录容器Webshell:
   cat /etc/nginx/nginx.conf | grep "try_files"
   
   应该看到:
   try_files $uri $uri/ /index.html;

解决方法:

如果nginx.conf中没有try_files配置,需要重新构建镜像:

# 在nginx.conf中确保有以下配置
location / {
    try_files $uri $uri/ /index.html;
}

问题4静态资源404

症状:

HTML能加载
JS/CSS文件404 Not Found
页面显示为纯文本(无样式)

排查步骤:

1. 检查浏览器Network标签
   看到:
   GET https://your-domain.com/assets/index-xxxxx.js 404

2. 检查index.html中的资源路径
   curl https://your-domain.com/ | grep assets
   
   正确示例:
   <script src="/assets/index-xxxxx.js"></script>
   
   错误示例:
   <script src="./assets/index-xxxxx.js"></script>  # 相对路径
   <script src="/app/assets/index-xxxxx.js"></script>  # 错误base

3. 检查Vite配置
   查看frontend-v2/vite.config.ts:
   
   正确配置:
   export default defineConfig({
     base: '/',  // ✅ 默认值
   })
   
   错误配置:
   export default defineConfig({
     base: '/app/',  // ❌ 除非确实需要
   })

解决方法:

  1. 修改 vite.config.ts,确保 base: '/'
  2. 重新构建前端:npm run build
  3. 重新构建Docker镜像
  4. 推送到ACR
  5. SAE重新部署

问题5环境变量未生效

症状:

配置了环境变量
但容器启动日志显示变量为空

排查步骤:

1. 查看容器启动日志
   【应用详情】→【日志】→【实时日志】
   
   看到:
   Backend Service: ${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT}
   
   ❌ 这说明envsubst没有替换变量

2. 进入容器Webshell检查
   echo $BACKEND_SERVICE_HOST
   
   如果为空 → SAE环境变量未传入
   如果有值 → envsubst执行失败

3. 检查docker-entrypoint.sh
   cat /docker-entrypoint.sh
   
   确认有:
   envsubst '${BACKEND_SERVICE_HOST} ${BACKEND_SERVICE_PORT}' \
     < /etc/nginx/templates/nginx.conf.template \
     > /etc/nginx/nginx.conf

解决方法:

  1. 在SAE控制台重新配置环境变量
  2. 确保变量名拼写正确(区分大小写)
  3. 重启应用使配置生效

10. 日常运维

📊 监控指标

实时监控

查看位置: 【应用详情】→【监控】

关键指标:
  CPU使用率:
    健康范围: < 30%
    告警阈值: > 60%
    说明: Nginx极少超过30%
  
  内存使用率:
    健康范围: < 50%
    告警阈值: > 80%
    说明: Nginx内存占用很低
  
  请求QPS:
    观察访问量趋势
  
  平均响应时间:
    健康范围: < 50ms
    告警阈值: > 200ms
    说明: 静态文件响应极快
  
  错误率:
    健康范围: < 0.1%
    告警阈值: > 1%

日志查看

实时日志:
  位置: 【应用详情】→【日志】→【实时日志】
  
  正常日志示例:
  172.17.0.10 - - [23/Dec/2025:10:30:00 +0800] "GET / HTTP/1.1" 200 1234
  172.17.0.10 - - [23/Dec/2025:10:30:01 +0800] "GET /assets/index.js HTTP/1.1" 200 567890
  
  API代理日志:
  172.17.0.10 - - [23/Dec/2025:10:30:02 +0800] "GET /api/v1/projects HTTP/1.1" 200 8765
  
  错误日志:
  2025/12/23 10:30:04 [error] connect() failed (111: Connection refused)
  → 后端服务连接失败

历史日志:
  位置: 【应用详情】→【日志】→【历史日志】
  保留时间: 7天

🔄 版本更新流程

当前端代码有更新时,按以下流程部署新版本:

步骤1本地构建新版本

# 在frontend-v2目录
cd AIclinicalresearch/frontend-v2

# 测试构建
npm run build

# 构建Docker镜像版本号+1
docker build -t frontend-service:v1.0.1 .

# 验证镜像大小
docker images frontend-service:v1.0.1

步骤2推送到ACR

# 登录ACR
echo fengzhibo117 | docker login --username=gofeng117@163.com --password-stdin crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com

# 打标签
docker tag frontend-service:v1.0.1 crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.1

docker tag frontend-service:v1.0.1 crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:latest

# 推送镜像
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.1

docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:latest

步骤3SAE灰度发布推荐

目的: 降低更新风险,先更新部分实例验证

操作步骤:
  1. 登录SAE控制台 → 进入应用详情
  
  2. 点击【部署】→【灰度发布】
  
  3. 配置灰度策略:
     灰度实例数: 1
     灰度时长: 5分钟
     镜像版本: v1.0.1
  
  4. 点击【确定】
  
  5. 观察灰度实例:
     - 查看实例状态(健康)
     - 查看错误日志(无错误)
     - 访问测试(功能正常)
  
  6. 确认无问题后,点击【全量发布】
  
  7. 如果发现问题,点击【回滚】
     - 自动回滚到上一个版本
     - 无需手动操作

步骤4全量发布

如果不使用灰度发布,直接全量更新:

操作步骤:
  1. 登录SAE控制台 → 进入应用详情
  
  2. 点击【部署】
  
  3. 修改镜像版本:
     : v1.0.0
     : v1.0.1
  
  4. 点击【确定】
  
  5. 等待部署完成2-3分钟
  
  6. 验证新版本:
     - 查看实例状态
     - 访问前端页面
     - 测试核心功能

🔙 回滚操作

如果新版本出现问题,可以快速回滚:

操作步骤:
  1. 登录SAE控制台 → 进入应用详情
  
  2. 点击【变更记录】
  
  3. 找到上一个稳定版本如v1.0.0
  
  4. 点击【回滚】
  
  5. 确认回滚
  
  6. 等待回滚完成1-2分钟

回滚时间:
  - 镜像已缓存: 1-2分钟
  - 镜像未缓存: 2-3分钟

🗑️ 清理旧版本镜像

定期清理ACR中的旧版本镜像节省存储空间

清理策略:
  - 保留最近3个版本
  - 删除30天前的旧版本
  - 保留带有特殊标签的版本如stable、prod

操作步骤:
  1. 登录ACR控制台
  
  2. 进入镜像仓库 → ai-clinical_frontend-nginx
  
  3. 查看所有版本
  
  4. 选择要删除的版本(勾选)
  
  5. 点击【删除】
  
  6. 确认删除

⚠️ 注意:
  - 不要删除正在使用的版本
  - 删除前确认SAE应用已更新到新版本
  - 建议至少保留2个版本以便回滚

📈 弹性伸缩配置

前端Nginx服务通常不需要频繁扩缩容但可以配置自动伸缩

配置位置: 【应用配置】→【弹性伸缩】

最小实例数: 2
  说明: 保证高可用至少2个实例

最大实例数: 5
  说明: 前端流量波动通常不大5个实例足够

扩容策略:
  指标: CPU使用率
  阈值: > 60% 持续 3分钟
  每次扩容: +1个实例
  冷却时间: 3分钟
  
  说明: Nginx很少达到60% CPU

缩容策略:
  指标: CPU使用率
  阈值: < 20% 持续 5分钟
  每次缩容: -1个实例
  冷却时间: 5分钟
  最小保留: 2个实例

⚠️ 实际情况:
  前端Nginx性能极高2个0.5核实例可以支撑:
  - 1000+ QPS静态文件
  - 100+ QPSAPI代理
  - 几乎不需要扩容

🚨 告警配置

配置关键指标告警,及时发现问题:

配置位置: 【云监控】→【应用监控】→【创建告警规则】

推荐告警规则:

1. 实例健康检查失败
   - 条件: 健康检查失败 > 3次
   - 级别: 紧急
   - 通知: 短信 + 钉钉

2. CPU使用率过高
   - 条件: CPU > 60% 持续 5分钟
   - 级别: 警告
   - 通知: 钉钉 + 邮件

3. 内存使用率过高
   - 条件: 内存 > 80% 持续 5分钟
   - 级别: 警告
   - 通知: 钉钉 + 邮件

4. 错误率过高
   - 条件: 错误率 > 1% 持续 3分钟
   - 级别: 紧急
   - 通知: 短信 + 钉钉

5. 平均响应时间过长
   - 条件: 响应时间 > 500ms 持续 5分钟
   - 级别: 警告
   - 通知: 钉钉 + 邮件

通知方式配置:
  - 钉钉机器人: 创建群聊机器人获取Webhook
  - 邮件: 配置告警联系人邮箱
  - 短信: 配置手机号(建议仅用于紧急告警)

📚 附录

📝 配置文件清单

部署过程中涉及的配置文件:

本地文件 (AIclinicalresearch/frontend-v2/):
  - Dockerfile (多阶段构建配置)
  - nginx.conf (Nginx服务器配置)
  - docker-entrypoint.sh (容器启动脚本)
  - .dockerignore (构建排除文件)

SAE配置 (在控制台配置):
  - 应用基本信息
  - 实例规格和数量
  - VPC网络配置
  - 镜像地址和版本
  - 环境变量
  - 健康检查
  - 公网访问配置

🔗 相关文档链接

阿里云官方文档:
  - SAE产品文档: https://help.aliyun.com/product/1172298.html
  - ACR产品文档: https://help.aliyun.com/product/60716.html
  - VPC产品文档: https://help.aliyun.com/product/27706.html

项目内部文档:
  - 前端Nginx部署指南: docs/05-部署文档/06-前端Nginx-SAE容器部署指南.md
  - 快速部署SOP: docs/05-部署文档/01-快速部署SOP-零基础版.md
  - 部署架构总览: docs/05-部署文档/00-部署架构总览.md

💡 最佳实践总结

安全性:
  ✅ 使用专有网络VPC隔离
  ✅ 环境变量存储敏感信息
  ✅ 启用HTTPS生产环境
  ✅ 配置安全组规则
  ✅ 隐藏Nginx版本号

性能:
  ✅ 启用Gzip压缩减少70%传输)
  ✅ 配置合理的缓存策略
  ✅ 使用CDN加速可选
  ✅ 优化Docker镜像大小

可靠性:
  ✅ 至少2个实例高可用
  ✅ 配置健康检查
  ✅ 启用自动伸缩
  ✅ 配置告警监控
  ✅ 灰度发布降低风险

可维护性:
  ✅ 使用语义化版本号
  ✅ 保留最近3个版本以便回滚
  ✅ 定期清理旧版本镜像
  ✅ 记录变更日志
  ✅ 文档及时更新

常见问题FAQ

Q1: 前端服务需要多大的规格?

A: 0.5核1GB足够。
   - Nginx极其高效占用资源很少
   - 0.5核可以支撑1000+ QPS
   - 不要过度配置浪费资源

Q2: 需要配置多少个实例?

A: 生产环境建议2个实例。
   - 保证高可用1个故障时另1个继续服务
   - 前端很少需要3个以上实例
   - 流量特别大时可以配置CDN

Q3: 如何知道后端服务的内网地址?

A: 从后端SAE应用获取
   1. 登录SAE控制台
   2. 进入后端应用详情
   3. 查看【应用访问配置】→【VPC内网访问地址】
   4. 复制IP地址格式172.17.x.x

Q4: 环境变量配置后没生效怎么办?

A: 需要重启应用:
   1. 修改环境变量
   2. 点击【重启】或【重新部署】
   3. 等待实例重启完成
   4. 查看启动日志确认变量值

Q5: 部署新版本后如何快速回滚?

A: SAE支持一键回滚
   1. 进入【变更记录】
   2. 找到上一个稳定版本
   3. 点击【回滚】
   4. 等待1-2分钟完成回滚

Q6: 如何配置HTTPS

A: 两种方式:
   1. 使用SAE提供的域名自动HTTPS
   2. 绑定自定义域名并上传SSL证书
   
   生产环境强烈建议使用HTTPS

Q7: 前端需要连接数据库吗?

A: 不需要。
   - 前端是纯静态资源HTML/JS/CSS
   - 只需要通过Nginx代理访问后端API
   - 数据库连接由后端服务处理

Q8: 每次更新都要重新构建Docker镜像吗

A: 是的。
   1. 修改前端代码
   2. npm run build生成新的dist/
   3. docker build打包到镜像
   4. docker push推送到ACR
   5. SAE重新部署拉取新镜像
   
   这是标准的容器化部署流程

Q9: Docker镜像太大怎么办

A: 当前镜像只有92MB已经很小了。
   - 多阶段构建(只保留运行时文件)
   - Alpine基础镜像最小Linux发行版
   - 已经是最优化的状态

Q10: 如何查看实时访问日志?

A: SAE控制台查看
   【应用详情】→【日志】→【实时日志】
   
   可以看到:
   - 所有HTTP请求URL、状态码、响应时间
   - Nginx错误日志
   - 容器启动日志

🎯 部署检查清单

最后,用这个清单确认部署完成:

部署前准备:
  ☑️ ACR镜像已推送v1.0.0
  ☑️ 后端服务已部署(获取内网地址)
  ☑️ VPC和交换机已创建
  ☑️ 安全组已配置

SAE应用配置:
  ☑️ 应用名称frontend-nginx-service
  ☑️ 实例规格0.5核1GB
  ☑️ 实例数量2
  ☑️ 镜像地址:专有网络域名(带-vpc
  ☑️ 镜像版本v1.0.0

环境变量配置:
  ☑️ BACKEND_SERVICE_HOST已配置172.17.x.x
  ☑️ BACKEND_SERVICE_PORT已配置3001

健康检查配置:
  ☑️ 检查路径:/health
  ☑️ 检查端口80
  ☑️ 检查协议HTTP

部署验证:
  ☑️ 实例状态:健康
  ☑️ 健康检查:通过
  ☑️ 主页访问:正常
  ☑️ SPA路由正常刷新不404
  ☑️ API代理正常无CORS错误
  ☑️ 静态资源:正常(缓存生效)
  ☑️ Gzip压缩已启用

监控和告警:
  ☑️ 实时监控:已配置
  ☑️ 日志查看:可访问
  ☑️ 告警规则:已配置

全部完成,部署成功!🎉

文档结束

如有疑问,请查阅相关文档或联系技术支持。

祝部署顺利!🚀