Monorepo容器部署中Express模块找不到的问题排查求助
问题分析
从你提供的错误日志和Dockerfile来看,核心问题是生产环境容器中缺少express依赖包,这通常是多阶段构建过程中依赖没有被正确复制或安装到最终镜像导致的。结合你的pnpm+Turbo monorepo架构,我整理了几个关键问题点和对应的修复方案:
关键问题定位
Turbo Prune可能遗漏间接依赖
你使用turbo prune --scope=@bics/api --docker时,默认仅包含目标包的直接依赖,如果express是作为间接依赖存在,或者Turbo的prune逻辑未正确识别,会导致out/json目录缺少express的依赖声明,后续安装环节自然会遗漏。生产依赖安装的时机与方式有误
Builder阶段执行的pnpm install --prod --filter @bics/api --frozen-lockfile可能存在问题:pnpm的--filter在生产安装时可能无法正确将依赖hoist到根node_modules,而你在Final阶段复制的是根node_modules,导致API服务无法找到依赖。Final阶段的文件复制路径不匹配pnpm依赖结构
pnpm默认采用非hoisted依赖结构,依赖会被安装在.pnpm目录并通过软链关联,直接复制根node_modules可能无法正确关联到express的实际安装位置。
具体修复方案
方案1:修正Turbo Prune命令,确保包含所有依赖
修改Base阶段的Turbo Prune命令,添加--include-dependencies参数,强制包含目标包的所有直接和间接依赖:
# Base阶段的RUN命令替换为 RUN pnpm dlx turbo prune @bics/api --include-dependencies --docker
这样能确保out/json目录包含express的依赖声明,避免Installer阶段安装遗漏。
方案2:调整生产依赖的安装与复制逻辑
在Final阶段直接从Builder复制API子包的完整依赖,而非根node_modules:
# Final阶段的COPY命令修改为 COPY --from=builder /app/apps/api/dist ./dist COPY --from=builder /app/apps/api/package.json ./package.json # 复制API子包的node_modules,而非根目录的 COPY --from=builder /app/apps/api/node_modules ./node_modules
同时,将Builder阶段的生产依赖安装命令调整为:
# Builder阶段最后一条RUN命令替换为 RUN pnpm install --prod --filter @bics/api... --frozen-lockfile
(...表示包含所有子依赖,确保安装完整的生产依赖树)
方案3:添加调试命令验证依赖存在性
在Builder或Final阶段添加调试命令,确认express是否被正确安装:
# 在Builder阶段添加 RUN pnpm list --filter @bics/api express # 检查API包是否依赖express RUN ls -la /app/node_modules/express # 检查根node_modules是否有express # 或者在Final阶段启动前添加 RUN ls -la /app/node_modules/express
如果输出显示express不存在,说明Installer阶段的依赖安装就有问题,需要检查pnpm-lock.yaml是否正确包含express条目。
方案4:检查并调整pnpm的hoisting配置
查看项目根目录的.npmrc文件,如果有hoist=false或strict-peer-dependencies=true等配置,可能导致依赖不被hoist到根node_modules。可以临时在Installer阶段添加环境变量强制hoist:
# 在Installer阶段添加 ENV PNPM_HOIST=true
这样能确保pnpm将依赖hoist到根node_modules,方便Final阶段复制后被API服务找到。
额外注意事项
- Node版本兼容性:Node v22是较新版本,需确保pnpm和Turbo的版本支持该Node版本。可以在Base阶段指定pnpm版本,比如
RUN corepack enable pnpm@9(根据你的pnpm-lock.yaml调整)。 - Turbo配置检查:确认
turbo.json的pipeline配置中,@bics/api的build任务是否正确依赖了依赖安装步骤,确保构建时所有依赖已就绪。
按照以上方案逐一排查,应该能解决express找不到的问题。如果仍未解决,可以提供@bics/api的package.json和根目录的pnpm-workspace.yaml,进一步分析依赖结构。
内容来源于stack exchange

