# AI临床研究平台 - 完整部署实战手册?025版) > **文档版本**:v1.0(实战版? > **创建日期**?025-12-25 > **基于实际部署**?025-12-24 ~ 2025-12-25 完整部署经历 > **部署成功时间**:约6小时(包含问题排查) > **部署人员**:开发团? > **部署结果**:✅ 完全成功,所有功能正常运? --- ## 📋 文档说明 ### 本文档的特点 - ?**基于真实部署经历**:记录了2025?2月实际部署的完整过程 - ?**包含所有坑?*:遇到的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元) - [ ] 地域选择:华?(北京) - [ ] 已创建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/ ``` --- ## 🌐 二、基础设施部署?小时? ### 2.1 VPC网络?5分钟? **登录VPC控制?*:https://vpc.console.aliyun.com/ #### 创建VPC 1. 点击【创建专有网络? 2. 配置参数? ```yaml VPC名称: ai-clinical-vpc 地域: 华北2(北京) IPv4网段: 172.17.0.0/16 ``` 3. 点击【确定? #### 创建交换机(2个,提高可用性) **交换?**? ```yaml 名称: ai-clinical-vsw-f 可用? 华北2 可用区F IPv4网段: 172.17.160.0/20 ``` **交换?**? ```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网关?5分钟? **用?*:让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?0分钟? **登录RDS控制?*:https://rdsnext.console.aliyun.com/ #### 创建实例 1. 点击【创建实例? 2. 配置参数? ```yaml # 基础配置 地域: 华北2(北京) 可用? 可用区F(与交换机对应) 数据库引? PostgreSQL 版本: 15 系列: 高可用版 存储类型: ESSD云盘 # 规格 规格类型: 通用? 规格: 2?GB (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对象存储?0分钟? **登录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容器镜像仓库?0分钟? **登录容器镜像服务**:https://cr.console.aliyun.com/ #### 创建命名空间 1. 进入【个人实例】→ 【命名空间? 2. 点击【创建命名空间】: ```yaml 命名空间名称: ai-clinical ``` #### 创建镜像仓库?个) **仓库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镜像?0分钟? #### 进入目录 ```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 # 等待推送完成(?-10分钟,镜像约1.1GB? # The push refers to repository [...] # v1.0: digest: sha256:... size: ... ``` --- ### 3.2 部署到SAE?5分钟? **登录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】(?-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后端部署?0分钟? ### 4.1 准备工作?0分钟? #### 生成强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镜像?0分钟? #### 方案选择 我们使用**方案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 # 等待推送完成(?0分钟,镜像约838MB? ``` --- ### 4.3 部署到SAE?0分钟? **登录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】(?0分钟? - 记录内网地址:`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部署?0分钟? ### 5.1 构建Docker镜像?5分钟? #### 进入目录 ```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 # 等待推送完成(?分钟,镜像约50MB? ``` --- ### 5.2 部署到SAE?5分钟? **登录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】(?分钟? - 记录内网地址:`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负载均衡配置?0分钟? ### 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?大功能全部报? ``` 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监听(端?43? 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?大功能正? - [ ] ?文件上传功能正常 - [ ] ?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应用启动失败** - 查看实例日志,找到具体错误信? - 参考本文档??关键经验与注意事? - 对照检查Dockerfile和环境变? --- ## 🎯 总结 恭喜!您已经完成了AI临床研究平台的完整部署! **部署成果**? - ?4个服务全部成功部署(Python、Node.js、前端、数据库? - ?所有功能正常运? - ?公网可以访问 - ?生产环境就绪 **部署时间**? - 预计时间?.5小时 - 实际时间:约6小时(包含问题排查) **关键经验**? - 环境变量名必须精确匹? - 区分"重启应用"?部署应用" - Dockerfile必须包含所有必需文件 - 使用VPC地址拉取镜像 - 健康检查初始延迟要足够 **下一?*? - 配置HTTPS - 绑定域名 - 配置监控告警 - 优化性能 - 配置自动备份 --- > **文档维护**:本文档基于2025-12-25实际部署经历编写,请根据实际情况更新 > **最后更?*?025-12-25 > **部署状?*:✅ 完全成功