Docker-Compose运行Node.js项目时依赖包找不到问题求助
Docker-Compose启动Node.js应用时依赖模块缺失问题解决
问题描述
项目为不含源码的发布包,本地执行npm install --no-package-lock后,通过node FrontServerEntryPoint.js --environment production启动应用完全正常;单独使用以下Dockerfile构建运行也无问题:
FROM node:16-alpine WORKDIR /var/www/example.com COPY . /var/www/example.com RUN npm install --no-package-lock CMD [ "node", "FrontServerEntryPoint.js", "--environment", "production" ]
但使用以下docker-compose.yaml启动时,出现依赖模块找不到的错误:
version: "3" services: node_js: container_name: FrontServer build: . ports: [ "3000:3000" ] # TODO depends_on: [ "Database ] volumes: - .:/var/www/example.jp database: container_name: Database image: postgres ports: [ "5432:5432" ] environment: - POSTGRES_PASSWORD=${DATABASE_PASSWORD} volumes: - Database:/data/example.jp volumes: Database: {}
错误信息:
Error: Cannot find module '@yamato-daiwa/es-extensions-nodejs' Require stack: - /var/www/example.jp/FrontServerEntryPoint.js at Function.Module._resolveFilename (node:internal/modules/cjs/loader:985:15) // ... code: 'MODULE_NOT_FOUND', requireStack: [ '/var/www/example.com/FrontServerEntryPoint.js' ]
项目package.json依赖列表确认该依赖已声明:
{ "private": "true", "dependencies": { "@nestjs/common": "9.0.11", "@nestjs/core": "9.0.11", "@nestjs/platform-express": "9.0.11", "@nestjs/typeorm": "9.0.1", "@yamato-daiwa/es-extensions": "1.6.0-alpha.4", "@yamato-daiwa/es-extensions-nodejs": "1.6.0-alpha.3", "express-handlebars": "6.0.6", "hbs": "4.2.0", "pg": "8.8.0", "typeorm": "0.3.7" } }
问题原因
- 路径拼写错误:Dockerfile设置的工作目录为
/var/www/example.com,构建阶段依赖安装在该目录的node_modules下;但docker-compose中挂载本地目录到了/var/www/example.jp,路径不一致导致容器运行时读取的是挂载的本地目录,而该目录下未安装依赖。 - 目录覆盖问题:即使路径正确,挂载本地目录会完全覆盖容器内对应目录,包括构建时安装好的
node_modules。若本地目录未提前安装依赖,就会触发依赖缺失错误。
解决方案
方案一:移除不必要的本地目录挂载(发布包场景推荐)
发布包无需本地代码热更新,直接移除docker-compose中node_js服务的volumes挂载配置,让容器使用构建阶段生成的完整目录(包含已安装的依赖):
version: "3" services: node_js: container_name: FrontServer build: . ports: [ "3000:3000" ] # TODO depends_on: [ "Database" ] # 修正原配置的语法错误,补充闭合引号 database: container_name: Database image: postgres ports: [ "5432:5432" ] environment: - POSTGRES_PASSWORD=${DATABASE_PASSWORD} volumes: - Database:/data/example.jp volumes: Database: {}
方案二:保留挂载但避免覆盖node_modules(调试场景适用)
若需要挂载本地目录,需修正路径拼写,并添加对node_modules的匿名挂载,防止本地目录覆盖容器内的依赖:
version: "3" services: node_js: container_name: FrontServer build: . ports: [ "3000:3000" ] # TODO depends_on: [ "Database" ] volumes: - .:/var/www/example.com # 修正路径为Dockerfile中的工作目录 - /var/www/example.com/node_modules # 保留容器内的node_modules,不被本地覆盖 database: container_name: Database image: postgres ports: [ "5432:5432" ] environment: - POSTGRES_PASSWORD=${DATABASE_PASSWORD} volumes: - Database:/data/example.jp volumes: Database: {}
内容的提问来源于stack exchange,提问作者Takeshi Tokugawa YD
相关产品推荐
相关产品推荐

