# ==================== 阶段 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 # 5a. tsc 不会复制 .json 文件,手动补充 src 中的 JSON 配置到 dist COPY src/modules/ssa/config/*.json ./dist/modules/ssa/config/ COPY src/modules/asl/fulltext-screening/prompts/*.json ./dist/modules/asl/fulltext-screening/prompts/ # 6. 复制配置文件(agents.yaml等) COPY config ./config # ==================== 阶段 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 COPY --from=builder --chown=nodejs:nodejs /app/config ./config # 创建上传目录(用于临时文件) 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"]