# AI临床研究平台 - 完整部署实战手册(2025版) > **文档版本**:v1.0(实战版) > **创建日期**:2025-12-25 > **基于实际部署**:2025-12-24 ~ 2025-12-25 完整部署经历 > **部署成功时间**:约6小时(包含问题排查) > **部署人员**:开发团队 > **部署结果**:✅ 完全成功,所有功能正常运行 --- ## 📋 文档说明 ### 本文档的特点 - ✅ **基于真实部署经历**:记录了2025年12月实际部署的完整过程 - ✅ **包含所有坑点**:遇到的4个关键问题及解决方案 - ✅ **经验总结**:提炼出的最佳实践和注意事项 - ✅ **可直接复制**:所有配置和命令都经过验证 - ✅ **适合快速部署**:跟着做就能成功 ### 与其他文档的关系 | 文档名称 | 用途 | 何时使用 | |---------|------|---------| | **本文档** | 实战部署完整流程 | ⭐ 新部署或重新部署时 | | `01-快速部署SOP-零基础版.md` | 零基础完整指南 | 从零开始学习时 | | `00-部署进度总览.md` | 资源速查索引 | 查询资源信息时 | | `12-Node.js后端-SAE部署操作手册.md` | 单服务部署 | 只部署某个服务时 | --- ## 🎯 部署架构总览 ``` 用户浏览器 ↓ HTTPS (公网) CLB负载均衡器 (公网IP: 8.140.53.236) ↓ HTTP (内网) 前端Nginx (SAE: 172.17.173.72:80) ↓ HTTP (内网, /api/v1/) Node.js后端 (SAE: 172.17.173.73:3001) ↓ HTTP (内网, /api/dc/) Python服务 (SAE: 172.17.173.66:8000) ↓ SQL (内网) RDS PostgreSQL (内网: pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432) ``` **关键依赖**: - 所有服务在同一个VPC内网(`172.17.0.0/16`) - 使用NAT网关访问外网(拉取镜像、调用LLM API) - CLB绑定前端,提供公网访问 --- ## 📊 部署顺序(严格按顺序执行) | 步骤 | 服务 | 预计时间 | 依赖项 | |------|------|---------|--------| | 1️⃣ | VPC网络 + NAT网关 | 15分钟 | 无 | | 2️⃣ | RDS PostgreSQL | 30分钟 | VPC | | 3️⃣ | OSS对象存储 | 10分钟 | 无 | | 4️⃣ | ACR容器镜像仓库 | 10分钟 | 无 | | 5️⃣ | Python微服务镜像构建 | 20分钟 | ACR | | 6️⃣ | Python微服务部署到SAE | 15分钟 | VPC, ACR | | 7️⃣ | Node.js后端镜像构建 | 30分钟 | ACR, RDS | | 8️⃣ | Node.js后端部署到SAE | 20分钟 | VPC, ACR, RDS, Python | | 9️⃣ | 前端Nginx镜像构建 | 15分钟 | ACR | | 🔟 | 前端Nginx部署到SAE | 15分钟 | VPC, ACR, Node.js | | 1️⃣1️⃣ | CLB负载均衡器 | 10分钟 | 前端Nginx | | 1️⃣2️⃣ | 全链路测试验证 | 30分钟 | 所有服务 | **总计**:约3.5小时(不含问题排查) --- ## 🔑 一、前置准备(30分钟) ### 1.1 阿里云账号与资源 **检查清单**: - [ ] 阿里云账号已实名认证 - [ ] 账户余额 ≥ 500元(建议1000元) - [ ] 地域选择:华北2(北京) - [ ] 已创建RAM访问密钥(用于Docker登录) ### 1.2 本地开发环境 **必需工具**: - [ ] Docker Desktop(Windows/Mac)或 Docker Engine(Linux) - [ ] Git(用于代码管理) - [ ] Node.js 22+(用于本地构建) - [ ] PowerShell 或 Bash(执行脚本) **验证命令**: ```bash docker --version # 应显示 Docker version 24.0+ git --version # 应显示 git version 2.x+ node --version # 应显示 v22.x.x ``` ### 1.3 项目代码准备 ```bash # 克隆项目(如果还没有) git clone AIclinicalresearch cd AIclinicalresearch # 确认项目结构 ls -la # 应该看到:backend/, frontend-v2/, extraction_service/, docs/ ``` --- ## 🌐 二、基础设施部署(1小时) ### 2.1 VPC网络(15分钟) **登录VPC控制台**:https://vpc.console.aliyun.com/ #### 创建VPC 1. 点击【创建专有网络】 2. 配置参数: ```yaml VPC名称: ai-clinical-vpc 地域: 华北2(北京) IPv4网段: 172.17.0.0/16 ``` 3. 点击【确定】 #### 创建交换机(2个,提高可用性) **交换机1**: ```yaml 名称: ai-clinical-vsw-f 可用区: 华北2 可用区F IPv4网段: 172.17.160.0/20 ``` **交换机2**: ```yaml 名称: ai-clinical-vsw-a 可用区: 华北2 可用区A IPv4网段: 172.17.192.0/20 ``` #### 创建安全组 1. 进入【安全组】页面 2. 创建安全组: ```yaml 名称: ai-clinical-sg 网络: ai-clinical-vpc ``` 3. 配置入方向规则: ```yaml # 允许VPC内网互通 协议: 全部 端口: -1/-1 授权对象: 172.17.0.0/16 # 允许HTTPS (443) 协议: TCP 端口: 443/443 授权对象: 0.0.0.0/0 # 允许HTTP (80) 协议: TCP 端口: 80/80 授权对象: 0.0.0.0/0 ``` --- ### 2.2 NAT网关(15分钟) **用途**:让VPC内的SAE应用能访问外网(拉取镜像、调用LLM API) #### 创建NAT网关 **登录NAT网关控制台**:https://vpc.console.aliyun.com/nat/ 1. 点击【创建NAT网关】 2. 配置参数: ```yaml 名称: NAT_airesearch 地域: 华北2(北京) VPC: ai-clinical-vpc 交换机: ai-clinical-vsw-f 网关类型: 增强型 付费模式: 按量付费 ``` 3. 点击【立即购买】 #### 创建并绑定EIP 1. 在NAT网关详情页,点击【绑定弹性公网IP】 2. 选择【购买新的EIP】: ```yaml 计费方式: 按使用流量 带宽峰值: 5Mbps(测试环境够用) ``` 3. 购买并绑定 #### 配置SNAT条目(关键!) 1. 进入NAT网关详情 → 【SNAT管理】 2. 添加SNAT条目1: ```yaml 交换机: ai-clinical-vsw-f 公网IP: 选择刚才的EIP ``` 3. 添加SNAT条目2: ```yaml 交换机: ai-clinical-vsw-a 公网IP: 选择刚才的EIP ``` **验证**: - SNAT条目状态显示【可用】✅ --- ### 2.3 RDS PostgreSQL(30分钟) **登录RDS控制台**:https://rdsnext.console.aliyun.com/ #### 创建实例 1. 点击【创建实例】 2. 配置参数: ```yaml # 基础配置 地域: 华北2(北京) 可用区: 可用区F(与交换机对应) 数据库引擎: PostgreSQL 版本: 15 系列: 高可用版 存储类型: ESSD云盘 # 规格 规格类型: 通用型 规格: 2核4GB (pg.n2.2c.1m) 存储空间: 100GB # 网络 网络类型: 专有网络 VPC: ai-clinical-vpc 交换机: ai-clinical-vsw-f # 付费 付费类型: 按量付费(测试)或 包年包月(生产) ``` 3. 点击【立即购买】 #### 创建数据库和账号 **等待实例创建完成(约10分钟)**,然后: 1. 进入实例详情 → 【账号管理】 2. 创建高权限账号: ```yaml 账号名称: airesearch 账号密码: Xibahe@fengzhibo117 # 改为您的强密码 账号类型: 高权限账号 ``` 3. 进入【数据库管理】 4. 创建数据库: ```yaml 数据库名称: ai_clinical_research 字符集: UTF8 排序规则: en_US.utf8 授权账号: airesearch (读写) ``` #### 配置白名单 1. 进入【数据安全性】→ 【白名单设置】 2. 修改默认分组: ```yaml 白名单: 172.17.0.0/16 # VPC网段 ``` #### 配置时区(重要!) 1. 进入【参数设置】 2. 搜索 `timezone` 3. 修改为:`Asia/Shanghai` 4. 点击【提交参数】 #### 导入数据 **方法1:使用本地数据库导出**(推荐) ```bash # 从本地Docker导出 docker exec ai-clinical-postgres pg_dump \ -U postgres \ -d ai_clinical_research \ --format=plain \ --no-owner \ --no-acl \ --encoding=UTF8 \ > rds_init.sql # 临时开启RDS外网地址(仅用于导入) # 在RDS控制台 → 数据库连接 → 申请外网地址 # 导入到RDS(需要容器内有psql客户端) cat rds_init.sql | docker exec -i -e PGPASSWORD="Xibahe@fengzhibo117" \ ai-clinical-postgres psql \ -h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \ -p 5432 -U airesearch -d ai_clinical_research # 导入完成后,立即关闭外网地址(安全) ``` **验证**: ```bash # 连接到RDS检查 docker exec -e PGPASSWORD="Xibahe@fengzhibo117" \ ai-clinical-postgres psql \ -h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \ -p 5432 -U airesearch -d ai_clinical_research \ -c "SELECT nspname FROM pg_namespace WHERE nspname LIKE '%_schema' ORDER BY nspname;" # 应该看到:asl_schema, dc_schema, platform_schema 等 ``` --- ### 2.4 OSS对象存储(10分钟) **登录OSS控制台**:https://oss.console.aliyun.com/ #### 创建Bucket 1. 点击【创建Bucket】 2. 配置参数: ```yaml Bucket名称: ai-clinical-research 地域: 华北2(北京) 存储类型: 标准存储 读写权限: 私有 存储冗余类型: 同城冗余存储 版本控制: 关闭 ``` 3. 点击【确定】 #### 创建RAM访问密钥 1. 进入【访问控制RAM】:https://ram.console.aliyun.com/ 2. 创建用户: ```yaml 登录名称: oss-bucket-writer 显示名称: OSS Bucket写入用户 访问方式: ✅ OpenAPI调用访问 ``` 3. 保存AccessKey: ```yaml AccessKeyId: LTAI5tB2Dt3NdvBL3G7nYGv7 AccessKeySecret: 1iSN9k39RkApP93QjUhC1DcPIeMG4V ``` **⚠️ 立即复制保存,后续无法查看!** 4. 为用户授权: - 选择用户 → 【添加权限】 - 选择权限:`AliyunOSSFullAccess`(或自定义权限) --- ### 2.5 ACR容器镜像仓库(10分钟) **登录容器镜像服务**:https://cr.console.aliyun.com/ #### 创建命名空间 1. 进入【个人实例】→ 【命名空间】 2. 点击【创建命名空间】: ```yaml 命名空间名称: ai-clinical ``` #### 创建镜像仓库(3个) **仓库1:Python微服务** ```yaml 命名空间: ai-clinical 仓库名称: python-extraction 仓库类型: 私有 摘要: Python文档提取服务 ``` **仓库2:Node.js后端** ```yaml 命名空间: ai-clinical 仓库名称: backend-service 仓库类型: 私有 摘要: Node.js后端API服务 ``` **仓库3:前端Nginx** ```yaml 命名空间: ai-clinical 仓库名称: ai-clinical_frontend-nginx 仓库类型: 私有 摘要: React前端Nginx服务 ``` #### 设置访问凭证 **在本地Docker登录ACR**: ```bash # 个人版ACR登录(公网地址) docker login \ --username=gofeng117@163.com \ --password=fengzhibo117 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com # 登录成功提示 # Login Succeeded ``` **记录镜像地址格式**: ```bash # 公网地址(本地推送用) crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/<仓库名>:<标签> # VPC地址(SAE拉取用) crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/<仓库名>:<标签> ``` --- ## 🐍 三、Python微服务部署(35分钟) ### 3.1 构建Docker镜像(20分钟) #### 进入目录 ```bash cd AIclinicalresearch/extraction_service ``` #### 检查Dockerfile 确认Dockerfile存在且内容正确: ```dockerfile # 应该包含: FROM python:3-slim # ... 安装依赖 COPY requirements-prod.txt . RUN pip install --no-cache-dir -r requirements-prod.txt # ... 复制代码 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ``` #### 构建镜像 ```bash # 构建镜像 docker build -t python-extraction:v1.0 . # 等待构建完成(约10-15分钟) # Successfully built... # Successfully tagged python-extraction:v1.0 ``` #### 本地测试(可选但推荐) ```bash # 运行容器 docker run -d -p 8000:8000 --name python-test python-extraction:v1.0 # 测试健康检查 curl http://localhost:8000/api/health # 应该返回: # { # "status": "healthy", # "checks": {...} # } # 停止容器 docker stop python-test docker rm python-test ``` #### 推送到ACR ```bash # 打标签 docker tag python-extraction:v1.0 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0 # 推送镜像 docker push \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0 # 等待推送完成(约5-10分钟,镜像约1.1GB) # The push refers to repository [...] # v1.0: digest: sha256:... size: ... ``` --- ### 3.2 部署到SAE(15分钟) **登录SAE控制台**:https://sae.console.aliyun.com/ #### 创建命名空间(首次) 1. 进入【命名空间】 2. 点击【创建命名空间】: ```yaml 命名空间ID: cn-beijing:test-airesearch 命名空间名称: 测试环境 ``` #### 创建应用 1. 点击【创建应用】 2. 应用基本信息: ```yaml 应用名称: python-extraction-test 命名空间: cn-beijing:test-airesearch # 实例规格 CPU: 1核 内存: 2GB 实例数: 1 # 应用部署方式 部署方式: 镜像 镜像类型: 容器镜像服务企业版/个人版 ``` 3. 选择镜像: ```yaml 地域: 华北2(北京) 命名空间: ai-clinical 仓库: python-extraction 镜像版本: v1.0 # ⚠️ 使用VPC地址(SAE内网拉取,免流量费) 镜像地址会自动转为VPC地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0 ``` 4. 配置镜像访问凭证: ```yaml 用户名: gofeng117@163.com 密码: fengzhibo117 ``` 5. 应用配置: ```yaml # 启动命令配置 启动命令: 留空(使用Dockerfile的CMD) # 端口配置 容器端口: 8000 协议: TCP ``` 6. 环境变量(可选): ```bash LOG_LEVEL=INFO TEMP_DIR=/tmp/extraction_service ``` 7. 网络配置: ```yaml VPC: ai-clinical-vpc 交换机: ai-clinical-vsw-f 安全组: ai-clinical-sg ``` 8. 健康检查: ```yaml # 存活检查(Liveness) 检查方式: HTTP 检查路径: /api/health 端口: 8000 初始延迟: 30秒 检查间隔: 10秒 检查超时: 5秒 不健康阈值: 3次 # 就绪检查(Readiness) 检查方式: HTTP 检查路径: /api/health 端口: 8000 初始延迟: 10秒 ``` 9. 点击【确认创建】 #### 等待部署完成 - 查看【实例部署】页面 - 状态变为【Running】(约5-10分钟) - 记录内网地址:`http://172.17.173.66:8000` #### 验证部署 ```bash # 方法1:在SAE应用内查看日志 # 应该看到: # INFO: Uvicorn running on http://0.0.0.0:8000 # INFO: Application startup complete # 方法2:从Node.js应用测试(部署后) curl http://172.17.173.66:8000/api/health ``` --- ## 🟢 四、Node.js后端部署(50分钟) ### 4.1 准备工作(10分钟) #### 生成强JWT密钥 ```bash # 在PowerShell或Bash中生成 openssl rand -hex 32 # 或 node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" # 示例输出(使用您自己生成的): # 8a3f9e7c2d1b5a4e6f8c9d0a3b5e7f1c2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4 ``` #### 准备环境变量清单 创建文件 `backend/.env.production`(不提交到Git): ```bash # ==================== 基础配置 ==================== NODE_ENV=production PORT=3001 LOG_LEVEL=info # ==================== 数据库连接 ==================== DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research?connection_limit=18&pool_timeout=10 # ==================== Python微服务 ⚠️ 关键!==================== EXTRACTION_SERVICE_URL=http://172.17.173.66:8000 # ==================== OSS对象存储 ==================== OSS_ACCESS_KEY_ID=LTAI5tB2Dt3NdvBL3G7nYGv7 OSS_ACCESS_KEY_SECRET=1iSN9k39RkApP93QjUhC1DcPIeMG4V OSS_BUCKET=ai-clinical-research OSS_ENDPOINT=oss-cn-beijing-internal.aliyuncs.com OSS_REGION=cn-beijing # ==================== JWT认证 ==================== JWT_SECRET=8a3f9e7c2d1b5a4e6f8c9d0a3b5e7f1c2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4 JWT_EXPIRES_IN=7d # ==================== LLM API密钥 ==================== DEEPSEEK_API_KEY=sk-7f8cc37a79fa4799860b38fc7ba2e150 DASHSCOPE_API_KEY=sk-75b4ff29a14a49e79667a331034f3298 # ==================== CloseAI配置 ==================== CLOSEAI_API_KEY=sk-cu0iepbXYGGx2jc7BqP6ogtSWmP6fk918qV3RUdtGC3Ed1po CLOSEAI_OPENAI_BASE_URL=https://api.openai-proxy.org/v1 CLOSEAI_CLAUDE_BASE_URL=https://api.openai-proxy.org/anthropic # ==================== Dify配置 ==================== DIFY_API_URL=http://localhost/v1 DIFY_API_KEY=dataset-mfvdiKvQ213NvxWm7RoYMN3c # ==================== Postgres-Only架构 ==================== QUEUE_TYPE=pgboss CACHE_TYPE=postgres ``` --- ### 4.2 构建Docker镜像(30分钟) #### 方案选择 我们使用**方案B:本地编译 + Docker打包**(最稳定) #### 步骤1:本地编译TypeScript ```bash cd AIclinicalresearch/backend # 安装依赖 npm install # 编译TypeScript npm run build # 验证编译结果 ls dist/ # 应该看到:index.js, common/, modules/ 等 ``` #### 步骤2:检查Dockerfile 确认Dockerfile内容正确: ```dockerfile FROM node:22-alpine WORKDIR /app # 复制package.json和package-lock.json COPY package*.json ./ # 只安装生产依赖 RUN npm ci --only=production --ignore-scripts # 复制编译后的代码 COPY dist ./dist # 复制Prisma客户端 COPY node_modules/.prisma ./node_modules/.prisma # 复制Prisma schema(用于runtime) COPY prisma ./prisma # ⚠️ 复制config目录(重要!) COPY config ./config # 暴露端口 EXPOSE 3001 # 启动命令 CMD ["node", "dist/index.js"] ``` **⚠️ 关键修复1**:必须包含 `COPY config ./config`,否则会报错 `ENOENT: no such file or directory, open '/app/config/agents.yaml'` #### 步骤3:构建镜像 ```bash # 构建镜像 docker build -t backend-service:v1.3 . # 等待构建完成(约5分钟) ``` #### 步骤4:本地测试(推荐) ```bash # 运行容器(连接本地数据库测试) docker run -d -p 3001:3001 \ -e NODE_ENV=production \ -e DATABASE_URL="postgresql://postgres:postgres@host.docker.internal:5432/ai_clinical_research" \ -e EXTRACTION_SERVICE_URL=http://host.docker.internal:8000 \ --name backend-test \ backend-service:v1.3 # 查看日志 docker logs -f backend-test # 应该看到: # ✅ Loaded 12 agent configurations # ✅ 数据库连接成功 # 🚀 AI临床研究平台 - 后端服务器启动成功! # 📍 服务地址: http://localhost:3001 # 测试健康检查 curl http://localhost:3001/health # 停止测试容器 docker stop backend-test docker rm backend-test ``` #### 步骤5:推送到ACR ```bash # 打标签 docker tag backend-service:v1.3 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3 # 推送镜像 docker push \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3 # 等待推送完成(约10分钟,镜像约838MB) ``` --- ### 4.3 部署到SAE(10分钟) **登录SAE控制台**:https://sae.console.aliyun.com/ #### 创建应用 1. 点击【创建应用】 2. 应用基本信息: ```yaml 应用名称: nodejs-backend-test 命名空间: cn-beijing:test-airesearch # 实例规格 CPU: 1核 内存: 2GB 实例数: 1 ``` 3. 选择镜像: ```yaml 镜像类型: 容器镜像服务企业版/个人版 地域: 华北2(北京) 命名空间: ai-clinical 仓库: backend-service 镜像版本: v1.3 # 镜像访问凭证 用户名: gofeng117@163.com 密码: fengzhibo117 ``` 4. 应用配置: ```yaml # 启动命令 启动命令: 留空(使用Dockerfile的CMD) # ⚠️ 关键:不要配置 /bin/bash,Alpine Linux没有bash! # 端口配置 容器端口: 3001 协议: TCP ``` 5. 环境变量(⚠️ 非常重要!): **复制上面准备的完整环境变量清单**,特别注意: ```bash # ⚠️ 最容易出错的环境变量 EXTRACTION_SERVICE_URL=http://172.17.173.66:8000 # 不是 PYTHON_SERVICE_URL!名字必须正确! DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research?connection_limit=18&pool_timeout=10 # 注意:@ 要写成 %40 ``` 6. 网络配置: ```yaml VPC: ai-clinical-vpc 交换机: ai-clinical-vsw-f 安全组: ai-clinical-sg ``` 7. 健康检查: ```yaml # 存活检查(Liveness) 检查方式: HTTP 检查路径: /health 端口: 3001 初始延迟: 60秒 # Node.js启动较慢 检查间隔: 10秒 # 就绪检查(Readiness) 检查方式: HTTP 检查路径: /health 端口: 3001 初始延迟: 30秒 ``` 8. 点击【确认创建】 #### 等待部署完成 - 查看【实例部署】页面 - 状态变为【Running】(约10分钟) - 记录内网地址:`http://172.17.173.73:3001` #### 验证部署 查看日志,确认以下信息: ```bash # ✅ 应该看到的日志: ✅ Loaded 12 agent configurations [PgBossQueue] Using PgBossQueue (Postgres-Only架构) [PostgresCacheAdapter] Cleanup task started ✅ 数据库连接成功! 📊 数据库版本: PostgreSQL 15.14 PythonExecutorService initialized: http://172.17.173.66:8000 # ⚠️ 确认这个! 🚀 AI临床研究平台 - 后端服务器启动成功! 📍 服务地址: http://localhost:3001 Server listening at http://172.17.173.73:3001 # ❌ 如果看到错误: ENOENT: no such file or directory, open '/app/config/agents.yaml' → Dockerfile缺少 COPY config ./config Error: unable to determine transport target for "pino-pretty" → src/index.ts 日志配置问题,需要条件判断环境 ReferenceError: require is not defined → healthCheck.ts 使用了require,需改为import ``` --- ### 4.4 常见问题修复 #### 问题1:config目录缺失 **错误**: ``` ENOENT: no such file or directory, open '/app/config/agents.yaml' ``` **解决**: ```dockerfile # 在Dockerfile中添加 COPY config ./config ``` #### 问题2:pino-pretty生产环境报错 **错误**: ``` Error: unable to determine transport target for "pino-pretty" ``` **解决**:修改 `src/index.ts` ```typescript const fastify = Fastify({ logger: config.nodeEnv === 'production' ? { level: config.logLevel } // 生产环境:简单JSON日志 : { // 开发环境:pino-pretty level: config.logLevel, transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'HH:MM:ss Z', ignore: 'pid,hostname', }, }, }, }); ``` #### 问题3:healthCheck require报错 **错误**: ``` ReferenceError: require is not defined in ES module ``` **解决**:修改 `src/common/health/healthCheck.ts` ```typescript import os from 'os'; // 添加导入 // 修改使用方式 checks.cpu = { usage: process.cpuUsage(), loadAverage: process.platform !== 'win32' ? os.loadavg() : 'N/A' // 使用import的os } ``` #### 问题4:bash路径错误 **错误**: ``` executable '/bin/bash' not found in $PATH ``` **解决**: - SAE启动命令留空,使用Dockerfile的CMD - 或使用 `/bin/sh` 代替 `/bin/bash` --- ## 🎨 五、前端Nginx部署(30分钟) ### 5.1 构建Docker镜像(15分钟) #### 进入目录 ```bash cd AIclinicalresearch/frontend-v2 ``` #### 检查关键文件 **1. Dockerfile**(多阶段构建): ```dockerfile # 第一阶段:构建React应用 FROM node:22-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # 第二阶段:Nginx托管 FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/templates/nginx.conf.template COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh EXPOSE 80 ENTRYPOINT ["/docker-entrypoint.sh"] ``` **2. docker-entrypoint.sh**(动态配置): ```bash #!/bin/bash set -e # ⚠️ 检查必需的环境变量 if [ -z "$BACKEND_SERVICE_HOST" ]; then echo "❌ ERROR: BACKEND_SERVICE_HOST environment variable is required!" exit 1 fi if [ -z "$BACKEND_SERVICE_PORT" ]; then export BACKEND_SERVICE_PORT=3001 # 默认值 fi # 使用envsubst动态替换配置 envsubst '${BACKEND_SERVICE_HOST} ${BACKEND_SERVICE_PORT}' \ < /etc/nginx/templates/nginx.conf.template \ > /etc/nginx/nginx.conf # 启动Nginx exec nginx -g 'daemon off;' ``` **3. nginx.conf**(使用变量占位符): ```nginx upstream backend { server ${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT} fail_timeout=30s max_fails=3; keepalive 32; } server { listen 80; root /usr/share/nginx/html; # API反向代理 location /api/ { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # ... } # SPA路由支持 location / { try_files $uri $uri/ /index.html; } } ``` #### 构建镜像 ```bash # 构建镜像 docker build -t ai-clinical_frontend-nginx:v1.0 . # 等待构建完成(约10分钟) # 第一阶段会构建React应用,第二阶段打包到Nginx ``` #### 本地测试 ```bash # 运行容器 docker run -d -p 3000:80 \ -e BACKEND_SERVICE_HOST=host.docker.internal \ -e BACKEND_SERVICE_PORT=3001 \ --name frontend-test \ ai-clinical_frontend-nginx:v1.0 # 访问前端 open http://localhost:3000 # 或 curl http://localhost:3000 # 停止容器 docker stop frontend-test docker rm frontend-test ``` #### 推送到ACR ```bash # 打标签 docker tag ai-clinical_frontend-nginx:v1.0 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0 # 推送镜像 docker push \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0 # 等待推送完成(约3分钟,镜像约50MB) ``` --- ### 5.2 部署到SAE(15分钟) **登录SAE控制台**:https://sae.console.aliyun.com/ #### 创建应用 1. 点击【创建应用】 2. 应用基本信息: ```yaml 应用名称: frontend-nginx-service 命名空间: cn-beijing:test-airesearch # 实例规格 CPU: 0.5核 内存: 1GB 实例数: 1 ``` 3. 选择镜像: ```yaml 镜像类型: 容器镜像服务企业版/个人版 地域: 华北2(北京) 命名空间: ai-clinical 仓库: ai-clinical_frontend-nginx 镜像版本: v1.0 # 镜像访问凭证 用户名: gofeng117@163.com 密码: fengzhibo117 ``` 4. 应用配置: ```yaml # 启动命令 启动命令: 留空(使用ENTRYPOINT) # 端口配置 容器端口: 80 协议: TCP ``` 5. 环境变量(⚠️ 关键配置): ```bash BACKEND_SERVICE_HOST=172.17.173.73 # Node.js后端内网IP BACKEND_SERVICE_PORT=3001 ``` 6. 网络配置: ```yaml VPC: ai-clinical-vpc 交换机: ai-clinical-vsw-f 安全组: ai-clinical-sg ``` 7. 健康检查: ```yaml # 存活检查 检查方式: HTTP 检查路径: /health 端口: 80 初始延迟: 10秒 检查间隔: 10秒 # 就绪检查 检查方式: HTTP 检查路径: /health 端口: 80 初始延迟: 5秒 ``` 8. 点击【确认创建】 #### 等待部署完成 - 查看【实例部署】页面 - 状态变为【Running】(约5分钟) - 记录内网地址:`http://172.17.173.72:80` #### 验证部署 查看日志: ```bash # ✅ 应该看到: ============================================ Starting Frontend Nginx Service Backend Service: 172.17.173.73:3001 ============================================ nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` --- ## 🌐 六、CLB负载均衡配置(10分钟) ### 6.1 配置公网访问 **方式1:SAE自动创建CLB(推荐)** 1. 进入SAE应用:`frontend-nginx-service` 2. 点击【公网访问】或【访问配置】Tab 3. 点击【添加公网访问】 4. 配置参数: ```yaml 负载均衡类型: 公网 负载均衡产品: CLB (传统型负载均衡) 付费模式: 按量付费 # 监听配置 协议: HTTP 端口: 80 后端端口: 80 # 健康检查 健康检查: 启用 检查路径: /health ``` 5. 点击【确定】 6. 等待2-3分钟,自动分配公网IP **方式2:手动创建CLB** 1. 登录CLB控制台:https://slb.console.aliyun.com/ 2. 创建负载均衡实例 3. 配置监听器(HTTP:80) 4. 添加后端服务器(前端Nginx的内网IP) 5. 配置健康检查 ### 6.2 获取公网地址 - 在SAE应用详情页查看【公网访问地址】 - 示例:`http://8.140.53.236/` - 复制此地址用于测试 --- ## ✅ 七、完整链路测试(30分钟) ### 7.1 基础功能测试 #### 测试1:前端页面访问 ```bash # 浏览器访问 http://8.140.53.236/ # 应该看到: ✅ React应用正常加载 ✅ 页面样式正常 ✅ 没有CORS错误 ``` #### 测试2:健康检查 ```bash # 后端健康检查(通过前端代理) curl http://8.140.53.236/api/v1/health # 或 curl http://172.17.173.73:3001/health # 应该返回: { "status": "ok", "timestamp": "...", "services": { "database": "connected", "cache": "available", "queue": "running" } } ``` #### 测试3:Python服务连接 ```bash # 直接测试Python服务 curl http://172.17.173.66:8000/api/health # 应该返回: { "status": "healthy", "checks": { "pymupdf": {"available": true, "version": "1.26.7"}, ... } } ``` --- ### 7.2 业务功能测试 #### 测试1:用户登录 1. 访问 http://8.140.53.236/ 2. 输入用户名密码 3. 点击登录 4. 查看浏览器Network面板: ``` Request URL: http://8.140.53.236/api/v1/auth/login Status: 200 OK ✅ Response: { "token": "...", "user": {...} } ``` #### 测试2:数据清洗模块(工具C) 1. 进入【数据清洗】→ 【工具C】 2. 上传Excel文件 3. 验证上传成功 4. 测试7大功能之一(如:数值映射): - 选择列 - 配置映射规则 - 点击【执行映射】 - 查看结果 **关键验证**: ``` 浏览器Network面板: POST http://8.140.53.236/api/v1/dc/tool-c/quick-action Status: 200 OK ✅ 后端日志: [QuickActionService] 调用重编码API: 性别 PythonExecutorService initialized: http://172.17.173.66:8000 ✅ [QuickActionService] 重编码成功 ✅ ``` #### 测试3:文献筛查模块(ASL) 1. 进入【文献筛查】模块 2. 创建项目 3. 上传文献 4. 执行智能筛查 5. 验证结果 --- ### 7.3 性能测试 #### 响应时间检查 ```bash # 使用curl测试响应时间 curl -w "@-" -o /dev/null -s http://8.140.53.236/ <<'EOF' time_namelookup: %{time_namelookup}\n time_connect: %{time_connect}\n time_appconnect: %{time_appconnect}\n time_pretransfer: %{time_pretransfer}\n time_redirect: %{time_redirect}\n time_starttransfer: %{time_starttransfer}\n ----------\n time_total: %{time_total}\n EOF # 期望结果: # time_total < 1秒(首次访问) # time_total < 0.3秒(后续访问) ``` --- ## 📊 八、部署成果总结 ### 8.1 已部署服务清单 | 服务 | 状态 | 内网地址 | 公网访问 | |------|------|---------|---------| | RDS PostgreSQL | ✅ | pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432 | ❌ | | Python微服务 | ✅ | 172.17.173.66:8000 | ❌ | | Node.js后端 | ✅ | 172.17.173.73:3001 | ❌ | | 前端Nginx | ✅ | 172.17.173.72:80 | ✅ | | CLB负载均衡 | ✅ | - | http://8.140.53.236/ | ### 8.2 关键配置速查 #### Python微服务环境变量 ```bash LOG_LEVEL=INFO TEMP_DIR=/tmp/extraction_service ``` #### Node.js后端关键环境变量 ```bash NODE_ENV=production PORT=3001 DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research EXTRACTION_SERVICE_URL=http://172.17.173.66:8000 # ⚠️ 关键!不是PYTHON_SERVICE_URL ``` #### 前端Nginx关键环境变量 ```bash BACKEND_SERVICE_HOST=172.17.173.73 # Node.js后端内网IP BACKEND_SERVICE_PORT=3001 ``` --- ## ⚠️ 九、关键经验与注意事项 ### 9.1 环境变量名必须精确 **问题**:工具C的7大功能全部报错 ``` connect ECONNREFUSED 127.0.0.1:8000 ``` **原因**:Node.js代码使用 `EXTRACTION_SERVICE_URL`,但SAE配置了 `PYTHON_SERVICE_URL` **解决**: ```bash # ❌ 错误 PYTHON_SERVICE_URL=http://172.17.173.66:8000 # ✅ 正确 EXTRACTION_SERVICE_URL=http://172.17.173.66:8000 ``` **教训**:环境变量名必须与代码完全一致,一个字母都不能错! --- ### 9.2 "重启应用" vs "部署应用" **问题**:点击"部署应用"导致IP地址变更 | 操作 | 用途 | IP是否变 | 何时使用 | |------|------|---------|---------| | **重启应用** | 重启容器 | ❌ 不会 | 修改环境变量后 | | **部署应用** | 更新镜像 | ✅ 会变 | 更新代码/镜像时 | **教训**: - 只修改环境变量 → 用"重启应用" - 更新代码/镜像 → 用"部署应用" --- ### 9.3 Dockerfile必须包含config目录 **问题**: ``` ENOENT: no such file or directory, open '/app/config/agents.yaml' ``` **解决**: ```dockerfile # ✅ 必须添加 COPY config ./config ``` --- ### 9.4 pino-pretty仅用于开发环境 **问题**: ``` Error: unable to determine transport target for "pino-pretty" ``` **原因**:`pino-pretty`是devDependencies,生产环境没有安装 **解决**:条件判断环境 ```typescript logger: config.nodeEnv === 'production' ? { level: config.logLevel } : { level: config.logLevel, transport: { target: 'pino-pretty', ... } } ``` --- ### 9.5 ES Module兼容性 **问题**: ``` ReferenceError: require is not defined in ES module ``` **解决**: ```typescript // ❌ 错误 require('os').loadavg() // ✅ 正确 import os from 'os'; os.loadavg() ``` --- ### 9.6 Alpine Linux没有bash **问题**: ``` executable '/bin/bash' not found in $PATH ``` **解决**: - SAE启动命令留空 - 或使用 `/bin/sh` 代替 --- ### 9.7 数据库URL中的@符号 **格式**: ```bash # ✅ 正确(URL编码) DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-xxx.pg.rds.aliyuncs.com:5432/ai_clinical_research # ❌ 错误(未编码) DATABASE_URL=postgresql://airesearch:Xibahe@fengzhibo117@pgm-xxx.pg.rds.aliyuncs.com:5432/ai_clinical_research ``` **规则**:密码中的 `@` 必须编码为 `%40` --- ### 9.8 使用VPC镜像地址(SAE拉取) **SAE部署时选择镜像**: ```bash # ✅ 正确(VPC地址,免流量费) crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3 # ❌ 不推荐(公网地址,收流量费) crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3 ``` **规则**: - 本地推送镜像 → 使用公网地址 - SAE拉取镜像 → 使用VPC地址 --- ### 9.9 健康检查初始延迟 **不同服务的启动时间**: | 服务 | 启动时间 | 初始延迟建议 | |------|---------|-------------| | Python微服务 | 10秒 | 30秒 | | Node.js后端 | 30秒 | 60秒 | | 前端Nginx | 5秒 | 10秒 | **教训**:Node.js启动较慢,需要更长的初始延迟 --- ### 9.10 前端动态配置后端地址 **架构优势**: - 前端使用环境变量 `BACKEND_SERVICE_HOST` - 通过 `envsubst` 在容器启动时动态注入 - 后端IP变更时,只需重启前端应用,无需重新构建镜像 **关键文件**: - `docker-entrypoint.sh`:动态替换配置 - `nginx.conf`:使用 `${BACKEND_SERVICE_HOST}` 占位符 --- ## 🚀 十、未来优化建议 ### 10.1 使用服务发现代替IP地址 **当前配置**(使用IP): ```bash BACKEND_SERVICE_HOST=172.17.173.73 EXTRACTION_SERVICE_URL=http://172.17.173.66:8000 ``` **优化方案**(使用服务名): ```bash BACKEND_SERVICE_HOST=nodejs-backend-test.cn-beijing:test-airesearch.svc.cluster.local EXTRACTION_SERVICE_URL=http://python-extraction-test.cn-beijing:test-airesearch.svc.cluster.local:8000 ``` **优点**: - ✅ IP变更不影响通信 - ✅ 自动负载均衡 - ✅ 更稳定可靠 --- ### 10.2 配置HTTPS **步骤**: 1. 申请域名 2. 申请SSL证书(阿里云免费证书或Let's Encrypt) 3. 在CLB配置HTTPS监听(端口443) 4. 上传SSL证书 5. 配置HTTP自动跳转HTTPS --- ### 10.3 配置自动扩缩容 **SAE弹性伸缩**: ```yaml # 根据CPU使用率自动扩缩容 最小实例数: 1 最大实例数: 3 目标CPU使用率: 70% ``` **适用场景**: - 流量波动大 - 高峰期需要更多实例 - 低峰期节约成本 --- ### 10.4 配置日志分析 **阿里云SLS(日志服务)**: - 自动收集SAE日志 - 实时查询和分析 - 配置告警规则 --- ### 10.5 配置监控告警 **云监控配置**: ```yaml CPU使用率 > 80% → 告警 内存使用率 > 80% → 告警 健康检查失败 → 告警 错误日志增多 → 告警 ``` --- ## 📝 十一、快速命令参考 ### 11.1 Docker镜像管理 ```bash # 登录ACR docker login --username=gofeng117@163.com \ --password=fengzhibo117 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com # 构建并推送Python镜像 cd AIclinicalresearch/extraction_service docker build -t python-extraction:v1.0 . docker tag python-extraction:v1.0 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0 docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0 # 构建并推送Node.js镜像 cd ../backend npm run build docker build -t backend-service:v1.3 . docker tag backend-service:v1.3 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3 docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.3 # 构建并推送前端镜像 cd ../frontend-v2 docker build -t ai-clinical_frontend-nginx:v1.0 . docker tag ai-clinical_frontend-nginx:v1.0 \ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0 docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0 ``` --- ### 11.2 数据库连接 ```bash # 连接到RDS(临时开启外网) docker exec -e PGPASSWORD="Xibahe@fengzhibo117" \ ai-clinical-postgres psql \ -h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \ -p 5432 -U airesearch -d ai_clinical_research # 查看Schema列表 docker exec -e PGPASSWORD="Xibahe@fengzhibo117" \ ai-clinical-postgres psql \ -h pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com \ -p 5432 -U airesearch -d ai_clinical_research \ -c "SELECT nspname FROM pg_namespace WHERE nspname LIKE '%_schema';" ``` --- ### 11.3 健康检查 ```bash # Python服务 curl http://172.17.173.66:8000/api/health # Node.js后端 curl http://172.17.173.73:3001/health # 前端Nginx curl http://172.17.173.72:80/health # 公网访问 curl http://8.140.53.236/ ``` --- ## 🎉 十二、部署完成检查清单 ### 最终验证 - [ ] ✅ Python微服务健康检查通过 - [ ] ✅ Node.js后端健康检查通过 - [ ] ✅ 前端Nginx健康检查通过 - [ ] ✅ 公网地址可以访问 - [ ] ✅ 用户可以正常登录 - [ ] ✅ 文献筛查功能正常 - [ ] ✅ 数据清洗工具C的7大功能正常 - [ ] ✅ 文件上传功能正常 - [ ] ✅ AI对话功能正常 - [ ] ✅ 没有CORS错误 - [ ] ✅ 没有502/504错误 - [ ] ✅ 响应时间 < 1秒 ### 文档更新 - [ ] 更新 `00-部署进度总览.md` 中的内网IP地址 - [ ] 记录公网访问地址 - [ ] 记录遇到的问题和解决方案 - [ ] 更新环境变量清单 --- ## 📞 十三、技术支持 ### 常见问题排查 **问题1:工具C功能报错 "connect ECONNREFUSED 127.0.0.1:8000"** - 检查Node.js环境变量 `EXTRACTION_SERVICE_URL` - 确保值为 `http://172.17.173.66:8000` - 重启Node.js应用 **问题2:前端访问后端报502错误** - 检查前端环境变量 `BACKEND_SERVICE_HOST` - 确保值为Node.js后端的内网IP - 重启前端应用 **问题3:SAE应用启动失败** - 查看实例日志,找到具体错误信息 - 参考本文档第9节"关键经验与注意事项" - 对照检查Dockerfile和环境变量 --- ## 🎯 总结 恭喜!您已经完成了AI临床研究平台的完整部署! **部署成果**: - ✅ 4个服务全部成功部署(Python、Node.js、前端、数据库) - ✅ 所有功能正常运行 - ✅ 公网可以访问 - ✅ 生产环境就绪 **部署时间**: - 预计时间:3.5小时 - 实际时间:约6小时(包含问题排查) **关键经验**: - 环境变量名必须精确匹配 - 区分"重启应用"和"部署应用" - Dockerfile必须包含所有必需文件 - 使用VPC地址拉取镜像 - 健康检查初始延迟要足够 **下一步**: - 配置HTTPS - 绑定域名 - 配置监控告警 - 优化性能 - 配置自动备份 --- > **文档维护**:本文档基于2025-12-25实际部署经历编写,请根据实际情况更新 > **最后更新**:2025-12-25 > **部署状态**:✅ 完全成功