Files
AIclinicalresearch/docs/05-部署文档/_archive-2025首次部署/17-完整部署实战手册-2025版.md
HaHafeng 6124c7abc6 docs(platform): Add database documentation system and restructure deployment docs
Completed:
- Add 6 core database documents (docs/01-平台基础层/07-数据库/)
  Architecture overview, migration history, environment comparison,
  tech debt tracking, seed data management, PostgreSQL extensions
- Restructure deployment docs: archive 20 legacy files to _archive-2025/
- Create unified daily operations manual (01-日常更新操作手册.md)
- Add pending deployment change tracker (03-待部署变更清单.md)
- Update database development standard to v3.0 (three iron rules)
- Fix Prisma schema type drift: align @db.* annotations with actual DB
  IIT: UUID/Timestamptz(6), SSA: Timestamp(6)/VarChar(20/50/100)
- Add migration: 20260227_align_schema_with_db_types (idempotent ALTER)
- Add Cursor Rule for auto-reminding deployment change documentation
- Update system status guide v6.4 with deployment and DB doc references
- Add architecture consultation docs (Prisma guide, SAE deployment guide)

Technical details:
- Manual migration due to shadow DB limitation (TD-001 in tech debt)
- Deployment docs reduced from 20+ scattered files to 3 core documents
- Cursor Rule triggers on schema.prisma, package.json, Dockerfile changes

Made-with: Cursor
2026-02-27 14:35:25 +08:00

40 KiB
Raw Blame History

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
11 CLB负载均衡器 10分钟 前端Nginx
12 全链路测试验证 30分钟 所有服务

总计约3.5小时(不含问题排查)


🔑 一、前置准备30分钟

1.1 阿里云账号与资源

检查清单

  • 阿里云账号已实名认证
  • 账户余额 ≥ 500元建议1000元
  • 地域选择华北2北京
  • 已创建RAM访问密钥用于Docker登录

1.2 本地开发环境

必需工具

  • Docker DesktopWindows/Mac或 Docker EngineLinux
  • Git用于代码管理
  • Node.js 22+(用于本地构建)
  • PowerShell 或 Bash执行脚本

验证命令

docker --version    # 应显示 Docker version 24.0+
git --version       # 应显示 git version 2.x+
node --version      # 应显示 v22.x.x

1.3 项目代码准备

# 克隆项目(如果还没有)
git clone <your-repo-url> 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. 配置参数:
    VPC名称: ai-clinical-vpc
    地域: 华北2北京
    IPv4网段: 172.17.0.0/16
    
  3. 点击【确定】

创建交换机2个提高可用性

交换机1

名称: ai-clinical-vsw-f
可用区: 华北2 可用区F
IPv4网段: 172.17.160.0/20

交换机2

名称: ai-clinical-vsw-a
可用区: 华北2 可用区A
IPv4网段: 172.17.192.0/20

创建安全组

  1. 进入【安全组】页面
  2. 创建安全组:
    名称: ai-clinical-sg
    网络: ai-clinical-vpc
    
  3. 配置入方向规则:
    # 允许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. 配置参数:
    名称: NAT_airesearch
    地域: 华北2北京
    VPC: ai-clinical-vpc
    交换机: ai-clinical-vsw-f
    网关类型: 增强型
    付费模式: 按量付费
    
  3. 点击【立即购买】

创建并绑定EIP

  1. 在NAT网关详情页点击【绑定弹性公网IP】
  2. 选择【购买新的EIP】
    计费方式: 按使用流量
    带宽峰值: 5Mbps测试环境够用
    
  3. 购买并绑定

配置SNAT条目关键

  1. 进入NAT网关详情 → 【SNAT管理】
  2. 添加SNAT条目1
    交换机: ai-clinical-vsw-f
    公网IP: 选择刚才的EIP
    
  3. 添加SNAT条目2
    交换机: ai-clinical-vsw-a
    公网IP: 选择刚才的EIP
    

验证

  • SNAT条目状态显示【可用】

2.3 RDS PostgreSQL30分钟

登录RDS控制台https://rdsnext.console.aliyun.com/

创建实例

  1. 点击【创建实例】
  2. 配置参数:
    # 基础配置
    地域: 华北2北京
    可用区: 可用区F与交换机对应
    数据库引擎: PostgreSQL
    版本: 15
    系列: 高可用版
    存储类型: ESSD云盘
    
    # 规格
    规格类型: 通用型
    规格: 2核4GB (pg.n2.2c.1m)
    存储空间: 100GB
    
    # 网络
    网络类型: 专有网络
    VPC: ai-clinical-vpc
    交换机: ai-clinical-vsw-f
    
    # 付费
    付费类型: 按量付费(测试)或 包年包月(生产)
    
  3. 点击【立即购买】

创建数据库和账号

等待实例创建完成约10分钟,然后:

  1. 进入实例详情 → 【账号管理】

  2. 创建高权限账号:

    账号名称: airesearch
    账号密码: Xibahe@fengzhibo117  # 改为您的强密码
    账号类型: 高权限账号
    
  3. 进入【数据库管理】

  4. 创建数据库:

    数据库名称: ai_clinical_research
    字符集: UTF8
    排序规则: en_US.utf8
    授权账号: airesearch (读写)
    

配置白名单

  1. 进入【数据安全性】→ 【白名单设置】
  2. 修改默认分组:
    白名单: 172.17.0.0/16  # VPC网段
    

配置时区(重要!)

  1. 进入【参数设置】
  2. 搜索 timezone
  3. 修改为:Asia/Shanghai
  4. 点击【提交参数】

导入数据

方法1使用本地数据库导出(推荐)

# 从本地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

# 导入完成后,立即关闭外网地址(安全)

验证

# 连接到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. 配置参数:
    Bucket名称: ai-clinical-research
    地域: 华北2北京
    存储类型: 标准存储
    读写权限: 私有
    存储冗余类型: 同城冗余存储
    版本控制: 关闭
    
  3. 点击【确定】

创建RAM访问密钥

  1. 进入【访问控制RAM】https://ram.console.aliyun.com/

  2. 创建用户:

    登录名称: oss-bucket-writer
    显示名称: OSS Bucket写入用户
    访问方式: ✅ OpenAPI调用访问
    
  3. 保存AccessKey

    AccessKeyId: LTAI5tB2Dt3NdvBL3G7nYGv7
    AccessKeySecret: 1iSN9k39RkApP93QjUhC1DcPIeMG4V
    

    ⚠️ 立即复制保存,后续无法查看!

  4. 为用户授权:

    • 选择用户 → 【添加权限】
    • 选择权限:AliyunOSSFullAccess(或自定义权限)

2.5 ACR容器镜像仓库10分钟

登录容器镜像服务https://cr.console.aliyun.com/

创建命名空间

  1. 进入【个人实例】→ 【命名空间】
  2. 点击【创建命名空间】:
    命名空间名称: ai-clinical
    

创建镜像仓库3个

仓库1Python微服务

命名空间: ai-clinical
仓库名称: python-extraction
仓库类型: 私有
摘要: Python文档提取服务

仓库2Node.js后端

命名空间: ai-clinical
仓库名称: backend-service
仓库类型: 私有
摘要: Node.js后端API服务

仓库3前端Nginx

命名空间: ai-clinical
仓库名称: ai-clinical_frontend-nginx
仓库类型: 私有
摘要: React前端Nginx服务

设置访问凭证

在本地Docker登录ACR

# 个人版ACR登录公网地址
docker login \
  --username=gofeng117@163.com \
  --password=fengzhibo117 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com

# 登录成功提示
# Login Succeeded

记录镜像地址格式

# 公网地址(本地推送用)
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分钟

进入目录

cd AIclinicalresearch/extraction_service

检查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"]

构建镜像

# 构建镜像
docker build -t python-extraction:v1.0 .

# 等待构建完成约10-15分钟
# Successfully built...
# Successfully tagged python-extraction:v1.0

本地测试(可选但推荐)

# 运行容器
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

# 打标签
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 部署到SAE15分钟

登录SAE控制台https://sae.console.aliyun.com/

创建命名空间(首次)

  1. 进入【命名空间】
  2. 点击【创建命名空间】:
    命名空间ID: cn-beijing:test-airesearch
    命名空间名称: 测试环境
    

创建应用

  1. 点击【创建应用】

  2. 应用基本信息:

    应用名称: python-extraction-test
    命名空间: cn-beijing:test-airesearch
    
    # 实例规格
    CPU: 1核
    内存: 2GB
    实例数: 1
    
    # 应用部署方式
    部署方式: 镜像
    镜像类型: 容器镜像服务企业版/个人版
    
  3. 选择镜像:

    地域: 华北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. 配置镜像访问凭证:

    用户名: gofeng117@163.com
    密码: fengzhibo117
    
  5. 应用配置:

    # 启动命令配置
    启动命令: 留空使用Dockerfile的CMD
    
    # 端口配置
    容器端口: 8000
    协议: TCP
    
  6. 环境变量(可选):

    LOG_LEVEL=INFO
    TEMP_DIR=/tmp/extraction_service
    
  7. 网络配置:

    VPC: ai-clinical-vpc
    交换机: ai-clinical-vsw-f
    安全组: ai-clinical-sg
    
  8. 健康检查:

    # 存活检查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

验证部署

# 方法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密钥

# 在PowerShell或Bash中生成
openssl rand -hex 32
# 或
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# 示例输出(使用您自己生成的):
# 8a3f9e7c2d1b5a4e6f8c9d0a3b5e7f1c2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4

准备环境变量清单

创建文件 backend/.env.production不提交到Git

# ==================== 基础配置 ====================
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

cd AIclinicalresearch/backend

# 安装依赖
npm install

# 编译TypeScript
npm run build

# 验证编译结果
ls dist/
# 应该看到index.js, common/, modules/ 等

步骤2检查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构建镜像

# 构建镜像
docker build -t backend-service:v1.3 .

# 等待构建完成约5分钟

步骤4本地测试推荐

# 运行容器(连接本地数据库测试)
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

# 打标签
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 部署到SAE10分钟

登录SAE控制台https://sae.console.aliyun.com/

创建应用

  1. 点击【创建应用】

  2. 应用基本信息:

    应用名称: nodejs-backend-test
    命名空间: cn-beijing:test-airesearch
    
    # 实例规格
    CPU: 1核
    内存: 2GB
    实例数: 1
    
  3. 选择镜像:

    镜像类型: 容器镜像服务企业版/个人版
    地域: 华北2北京
    命名空间: ai-clinical
    仓库: backend-service
    镜像版本: v1.3
    
    # 镜像访问凭证
    用户名: gofeng117@163.com
    密码: fengzhibo117
    
  4. 应用配置:

    # 启动命令
    启动命令: 留空使用Dockerfile的CMD
    
    # ⚠️ 关键:不要配置 /bin/bashAlpine Linux没有bash
    
    # 端口配置
    容器端口: 3001
    协议: TCP
    
  5. 环境变量(⚠️ 非常重要!):

    复制上面准备的完整环境变量清单,特别注意:

    # ⚠️ 最容易出错的环境变量
    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. 网络配置:

    VPC: ai-clinical-vpc
    交换机: ai-clinical-vsw-f
    安全组: ai-clinical-sg
    
  7. 健康检查:

    # 存活检查Liveness
    检查方式: HTTP
    检查路径: /health
    端口: 3001
    初始延迟: 60秒  # Node.js启动较慢
    检查间隔: 10秒
    
    # 就绪检查Readiness
    检查方式: HTTP
    检查路径: /health
    端口: 3001
    初始延迟: 30秒
    
  8. 点击【确认创建】

等待部署完成

  • 查看【实例部署】页面
  • 状态变为【Running】约10分钟
  • 记录内网地址:http://172.17.173.73:3001

验证部署

查看日志,确认以下信息:

# ✅ 应该看到的日志:
✅ 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 常见问题修复

问题1config目录缺失

错误

ENOENT: no such file or directory, open '/app/config/agents.yaml'

解决

# 在Dockerfile中添加
COPY config ./config

问题2pino-pretty生产环境报错

错误

Error: unable to determine transport target for "pino-pretty"

解决:修改 src/index.ts

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',
          },
        },
      },
});

问题3healthCheck require报错

错误

ReferenceError: require is not defined in ES module

解决:修改 src/common/health/healthCheck.ts

import os from 'os';  // 添加导入

// 修改使用方式
checks.cpu = {
  usage: process.cpuUsage(),
  loadAverage: process.platform !== 'win32' ? os.loadavg() : 'N/A'  // 使用import的os
}

问题4bash路径错误

错误

executable '/bin/bash' not found in $PATH

解决

  • SAE启动命令留空使用Dockerfile的CMD
  • 或使用 /bin/sh 代替 /bin/bash

🎨 五、前端Nginx部署30分钟

5.1 构建Docker镜像15分钟

进入目录

cd AIclinicalresearch/frontend-v2

检查关键文件

1. 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(动态配置):

#!/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(使用变量占位符):

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;
    }
}

构建镜像

# 构建镜像
docker build -t ai-clinical_frontend-nginx:v1.0 .

# 等待构建完成约10分钟
# 第一阶段会构建React应用第二阶段打包到Nginx

本地测试

# 运行容器
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

# 打标签
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 部署到SAE15分钟

登录SAE控制台https://sae.console.aliyun.com/

创建应用

  1. 点击【创建应用】

  2. 应用基本信息:

    应用名称: frontend-nginx-service
    命名空间: cn-beijing:test-airesearch
    
    # 实例规格
    CPU: 0.5核
    内存: 1GB
    实例数: 1
    
  3. 选择镜像:

    镜像类型: 容器镜像服务企业版/个人版
    地域: 华北2北京
    命名空间: ai-clinical
    仓库: ai-clinical_frontend-nginx
    镜像版本: v1.0
    
    # 镜像访问凭证
    用户名: gofeng117@163.com
    密码: fengzhibo117
    
  4. 应用配置:

    # 启动命令
    启动命令: 留空使用ENTRYPOINT
    
    # 端口配置
    容器端口: 80
    协议: TCP
    
  5. 环境变量(⚠️ 关键配置):

    BACKEND_SERVICE_HOST=172.17.173.73  # Node.js后端内网IP
    BACKEND_SERVICE_PORT=3001
    
  6. 网络配置:

    VPC: ai-clinical-vpc
    交换机: ai-clinical-vsw-f
    安全组: ai-clinical-sg
    
  7. 健康检查:

    # 存活检查
    检查方式: HTTP
    检查路径: /health
    端口: 80
    初始延迟: 10秒
    检查间隔: 10秒
    
    # 就绪检查
    检查方式: HTTP
    检查路径: /health
    端口: 80
    初始延迟: 5秒
    
  8. 点击【确认创建】

等待部署完成

  • 查看【实例部署】页面
  • 状态变为【Running】约5分钟
  • 记录内网地址:http://172.17.173.72:80

验证部署

查看日志:

# ✅ 应该看到:
============================================
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 配置公网访问

方式1SAE自动创建CLB推荐

  1. 进入SAE应用frontend-nginx-service
  2. 点击【公网访问】或【访问配置】Tab
  3. 点击【添加公网访问】
  4. 配置参数:
    负载均衡类型: 公网
    负载均衡产品: 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前端页面访问

# 浏览器访问
http://8.140.53.236/

# 应该看到:
✅ React应用正常加载
✅ 页面样式正常
✅ 没有CORS错误

测试2健康检查

# 后端健康检查(通过前端代理)
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"
  }
}

测试3Python服务连接

# 直接测试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 性能测试

响应时间检查

# 使用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微服务环境变量

LOG_LEVEL=INFO
TEMP_DIR=/tmp/extraction_service

Node.js后端关键环境变量

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关键环境变量

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

解决

# ❌ 错误
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'

解决

# ✅ 必须添加
COPY config ./config

9.4 pino-pretty仅用于开发环境

问题

Error: unable to determine transport target for "pino-pretty"

原因pino-pretty是devDependencies生产环境没有安装

解决:条件判断环境

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

解决

// ❌ 错误
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中的@符号

格式

# ✅ 正确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部署时选择镜像

# ✅ 正确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

BACKEND_SERVICE_HOST=172.17.173.73
EXTRACTION_SERVICE_URL=http://172.17.173.66:8000

优化方案(使用服务名):

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弹性伸缩

# 根据CPU使用率自动扩缩容
最小实例数: 1
最大实例数: 3
目标CPU使用率: 70%

适用场景

  • 流量波动大
  • 高峰期需要更多实例
  • 低峰期节约成本

10.4 配置日志分析

阿里云SLS日志服务

  • 自动收集SAE日志
  • 实时查询和分析
  • 配置告警规则

10.5 配置监控告警

云监控配置

CPU使用率 > 80%  → 告警
内存使用率 > 80% → 告警
健康检查失败    → 告警
错误日志增多    → 告警

📝 十一、快速命令参考

11.1 Docker镜像管理

# 登录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 数据库连接

# 连接到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 健康检查

# 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
  • 重启前端应用

问题3SAE应用启动失败

  • 查看实例日志,找到具体错误信息
  • 参考本文档第9节"关键经验与注意事项"
  • 对照检查Dockerfile和环境变量

🎯 总结

恭喜您已经完成了AI临床研究平台的完整部署

部署成果

  • 4个服务全部成功部署Python、Node.js、前端、数据库
  • 所有功能正常运行
  • 公网可以访问
  • 生产环境就绪

部署时间

  • 预计时间3.5小时
  • 实际时间约6小时包含问题排查

关键经验

  • 环境变量名必须精确匹配
  • 区分"重启应用"和"部署应用"
  • Dockerfile必须包含所有必需文件
  • 使用VPC地址拉取镜像
  • 健康检查初始延迟要足够

下一步

  • 配置HTTPS
  • 绑定域名
  • 配置监控告警
  • 优化性能
  • 配置自动备份

文档维护本文档基于2025-12-25实际部署经历编写请根据实际情况更新
最后更新2025-12-25
部署状态 完全成功