Files
AIclinicalresearch/docs/05-部署文档/_archive-2025首次部署/10-Node.js后端-Docker镜像构建手册.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

629 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Node.js 后端 - Docker 镜像构建操作手册
**文档版本**: v1.0
**创建时间**: 2024-12-24
**适用范围**: AIclinicalresearch 平台 - Node.js 后端服务
**目标读者**: 运维工程师、后端开发工程师
---
## 📋 目录
1. [构建概述](#构建概述)
2. [前置准备](#前置准备)
3. [构建流程](#构建流程)
4. [镜像信息](#镜像信息)
5. [故障排查](#故障排查)
6. [最佳实践](#最佳实践)
---
## 1. 构建概述
### 1.1 构建策略
本次构建采用**改进版方案B本地编译+Docker打包**,相比传统方案有以下优势:
| 对比项 | 传统方案 | 改进版方案B |
|--------|----------|-------------|
| **TypeScript编译** | Docker中执行 | 本地预编译 ✅ |
| **依赖安装** | 完整依赖 | 仅生产依赖 ✅ |
| **网络依赖** | 高(易超时) | 低(更稳定) ✅ |
| **构建时间** | ~10分钟 | ~5分钟 ✅ |
| **平台兼容性** | 有风险 | 无风险 ✅ |
### 1.2 构建成果
```
镜像名称: backend-service:v1.0
镜像大小: 838MB (压缩后 ~186MB)
镜像ID: a4ffb61c15af
构建时间: ~5分钟
ACR地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
```
---
## 2. 前置准备
### 2.1 环境检查
```powershell
# 1. 检查Docker状态
docker --version
docker ps
# 2. 检查Node.js环境
node --version # 应该显示 v22.x
npm --version
# 3. 确认当前目录
cd D:\MyCursor\AIclinicalresearch\backend
```
### 2.2 代码准备
#### ✅ 必须完成的步骤
**步骤1Prisma反向同步必须**
```powershell
# 设置临时RDS连接环境变量
$env:DATABASE_URL = "postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5oo.pg.rds.aliyuncs.com:5432/ai_clinical_research?connection_limit=18&pool_timeout=10"
# 执行Prisma反向同步
npx prisma db pull
# 输出应该显示:
# ✔ Introspected 32 models and wrote them into prisma\schema.prisma
```
**步骤2生成Prisma Client**
```powershell
npx prisma generate
# 输出应该显示:
# ✔ Generated Prisma Client (v6.17.0)
```
**步骤3TypeScript编译必须**
```powershell
# 编译TypeScript代码
npm run build
# 成功输出:
# > ai-clinical-backend@1.0.0 build
# > tsc
# (无错误信息)
# 检查dist目录是否生成
ls dist
```
⚠️ **重要提示**如果编译失败必须先修复所有TypeScript错误
---
## 3. 构建流程
### 3.1 完整构建步骤
```powershell
# 1. 确保在backend目录
cd D:\MyCursor\AIclinicalresearch\backend
# 2. 检查Dockerfile和.dockerignore
ls Dockerfile
ls .dockerignore
# 3. 开始构建需要5分钟
docker build -t backend-service:v1.0 .
# 4. 查看构建结果
docker images backend-service:v1.0
```
### 3.2 构建过程说明
**阶段1依赖安装约4分钟**
```dockerfile
FROM node:alpine AS builder
RUN apk add --no-cache openssl
COPY package*.json ./
COPY prisma ./prisma/
RUN npm ci --production # 仅安装生产依赖
RUN npx prisma generate # 生成Prisma Client
```
**阶段2复制本地编译结果约10秒**
```dockerfile
COPY dist ./dist # 复制本地已编译的TypeScript代码
```
**阶段3运行镜像打包约1分钟**
```dockerfile
FROM node:alpine
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/prisma ./prisma
```
### 3.3 推送到ACR
```powershell
# 1. 登录ACR使用个人版实例地址
echo "fengzhibo117" | docker login --username=gofeng117@163.com --password-stdin crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
# 输出Login Succeeded
# 2. 打标签
docker tag backend-service:v1.0 crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
docker tag backend-service:v1.0 crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:latest
# 3. 推送镜像
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:latest
# 输出:
# v1.0: digest: sha256:a4ffb61c15af... size: 856
# latest: digest: sha256:a4ffb61c15af... size: 856
```
---
## 4. 镜像信息
### 4.1 镜像地址
**VPC内网地址SAE部署使用**
```
crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
```
**公网地址(查看和拉取):**
```
crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
```
### 4.2 镜像详情
```yaml
镜像摘要: sha256:a4ffb61c15af1cd1ed9de187b4464a1aab773918e5b41b4df5b8ad96514f9941
大小: 838MB (压缩后 ~186MB)
架构: linux/amd64
基础镜像: node:alpine
Node版本: 22.x
标签: v1.0, latest
```
### 4.3 镜像内容
```
/app/
├── node_modules/ # 生产依赖
├── dist/ # 编译后的JS代码
├── prisma/ # Prisma Schema
│ └── schema.prisma
├── package.json
└── uploads/ # 临时文件目录
```
### 4.4 启动命令
```dockerfile
CMD ["node", "dist/index.js"]
```
### 4.5 健康检查
```dockerfile
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD node -e "require('http').get('http://localhost:3001/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1); })"
```
---
## 5. 故障排查
### 5.1 常见问题
#### ❌ 问题1TypeScript编译失败
**症状:**
```
error TS2554: Expected 2-3 arguments, but got 1.
error TS2322: Type 'XXX' is not assignable to type 'YYY'.
```
**原因:**
- Prisma反向同步后缺少关系字段
- 代码与Prisma生成的类型不匹配
**解决方案:**
```powershell
# 1. 重新同步Prisma
npx prisma db pull
npx prisma generate
# 2. 重新编译
npm run build
# 3. 如果还有错误检查tsconfig.json配置
```
#### ❌ 问题2Docker构建网络超时
**症状:**
```
npm error code ECONNRESET
npm error network aborted
```
**原因:**
- npm镜像源网络不稳定
- npm ci 下载依赖失败
**解决方案:**
**使用改进版方案B本次采用的方案**
- 本地预编译跳过Docker中的编译步骤
- 只安装生产依赖,减少网络传输
#### ❌ 问题3推送到ACR失败403 Forbidden
**症状:**
```
Error response from daemon: login attempt to https://registry.cn-beijing.aliyuncs.com/v2/ failed with status: 403 Forbidden
```
**原因:**
- 使用了错误的ACR地址
- 应该使用个人版实例地址,不是企业版地址
**解决方案:**
```powershell
# ✅ 正确的登录地址(个人版实例)
docker login crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
# ❌ 错误的登录地址(企业版)
docker login registry.cn-beijing.aliyuncs.com
```
#### ❌ 问题4VPC内网地址推送超时
**症状:**
```
failed to do request: Head "https://crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/...": net/http: TLS handshake timeout
```
**原因:**
- VPC内网地址只能在阿里云VPC内访问
- 本地开发环境无法访问VPC内网
**解决方案:**
```powershell
# 本地开发环境使用公网地址推送
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
# SAE部署时使用VPC内网地址拉取在SAE控制台配置
```
### 5.2 验证镜像
```powershell
# 1. 检查镜像是否存在
docker images backend-service:v1.0
# 2. 查看镜像详细信息
docker inspect backend-service:v1.0
# 3. 测试运行镜像(可选)
docker run -d `
--name backend-test `
-p 3001:3001 `
-e DATABASE_URL="postgresql://..." `
-e NODE_ENV=production `
backend-service:v1.0
# 4. 查看容器日志
docker logs backend-test
# 5. 测试健康检查
curl http://localhost:3001/health
# 6. 清理测试容器
docker stop backend-test
docker rm backend-test
```
---
## 6. 最佳实践
### 6.1 构建前检查清单
- [ ] 已完成Prisma反向同步`npx prisma db pull`
- [ ] 已生成Prisma Client`npx prisma generate`
- [ ] TypeScript编译成功`npm run build`
- [ ] dist目录已生成且包含所有编译后的JS文件
- [ ] Docker Desktop已启动并运行
- [ ] 网络连接正常
### 6.2 版本管理
**镜像标签规范:**
```
v1.0 - 特定版本(推荐用于生产环境)
latest - 最新版本(用于测试环境)
v1.0.1 - Bug修复版本
v1.1.0 - 功能更新版本
```
**推送策略:**
```powershell
# 生产环境部署(推送特定版本)
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
# 测试环境部署同时推送latest
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:latest
```
### 6.3 构建优化
**1. 利用Docker缓存**
```dockerfile
# ✅ 先复制package.json利用依赖缓存
COPY package*.json ./
RUN npm ci --production
# ✅ 最后复制代码,代码变化不影响依赖层缓存
COPY dist ./dist
```
**2. 使用.dockerignore**
```
node_modules
.env
.env.*
dist # 本地dist通过COPY显式复制
test
tests
*.md
.git
```
**3. 多阶段构建**
```dockerfile
# 阶段1依赖安装
FROM node:alpine AS builder
...
# 阶段2运行时镜像更小
FROM node:alpine
COPY --from=builder ...
```
### 6.4 安全建议
1. **不要在镜像中包含敏感信息**
- ❌ 不要把`.env`文件复制到镜像
- ✅ 使用SAE环境变量注入配置
2. **使用非root用户运行**
```dockerfile
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
USER nodejs
```
3. **定期更新基础镜像**
```dockerfile
FROM node:alpine # 使用最新的Alpine版本
```
---
## 附录ADockerfile完整内容
```dockerfile
# ==================== 阶段 1: 依赖安装阶段 ====================
FROM node:alpine AS builder
# 替换Alpine镜像源为阿里云镜像解决网络问题
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# 安装 Prisma 运行时依赖
RUN apk add --no-cache openssl
WORKDIR /app
# 1. 复制依赖文件
COPY package*.json ./
# 2. 复制 Prisma Schema用于生成Prisma Client
COPY prisma ./prisma/
# 3. 只安装生产依赖(大幅减少网络传输和安装时间)
RUN npm config set registry https://registry.npmmirror.com && \
npm config set fetch-retry-mintimeout 20000 && \
npm config set fetch-retry-maxtimeout 120000 && \
npm config set fetch-retries 5 && \
npm ci --production --prefer-offline --no-audit
# 4. 生成 Prisma Client生产环境需要
RUN npx prisma generate
# 5. 复制本地已编译好的 dist 文件夹跳过TypeScript编译
COPY dist ./dist
# ==================== 阶段 2: 运行阶段 ====================
FROM node:alpine
# 替换Alpine镜像源为阿里云镜像解决网络问题
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# 安装运行时依赖 + 时区数据
RUN apk add --no-cache \
openssl \
curl \
ca-certificates \
tzdata
# ⚠️ 统一时区Asia/Shanghai
ENV TZ=Asia/Shanghai
# 创建非 root 用户(安全最佳实践)
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
# 从构建阶段复制产物
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
COPY --from=builder --chown=nodejs:nodejs /app/prisma ./prisma
# 创建上传目录(用于临时文件)
RUN mkdir -p /app/uploads && chown -R nodejs:nodejs /app/uploads
# 切换到非 root 用户
USER nodejs
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD node -e "require('http').get('http://localhost:3001/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1); })"
# 暴露端口
EXPOSE 3001
# 🔥 启动命令(仅启动应用,不执行数据库迁移)
CMD ["node", "dist/index.js"]
```
---
## 附录B.dockerignore完整内容
```
# Node.js
node_modules
npm-debug.log
yarn-error.log
# 开发文件
.env
.env.*
*.local
# 构建产物改进方案B使用本地编译好的dist
# dist # 暂时注释掉允许复制本地dist
# 测试文件
test
tests
*.test.ts
*.spec.ts
coverage
# 文档和临时文件
docs
*.md
.vscode
.idea
.DS_Store
Thumbs.db
# 上传文件(运行时生成)
uploads/*
# Git
.git
.gitignore
# 日志
*.log
logs
# 临时文件
temp
tmp
*.swp
*.swo
*~
# 数据库文件SQLite如果有
*.db
*.sqlite
# 脚本文件(仅开发使用)
scripts/*.ts
*.bat
*.ps1
```
---
## 附录C相关文档
- [Node.js后端-SAE容器部署指南](./05-Node.js后端-SAE容器部署指南.md)
- [部署进度总览](./00-部署进度总览.md)
- [PostgreSQL数据库部署操作手册](./08-PostgreSQL数据库部署操作手册.md)
- [Python微服务-SAE部署操作手册](./09-Python微服务-SAE部署操作手册.md)
---
**文档维护者**: AI Assistant
**最后更新**: 2024-12-24
**版本**: v1.0