首次运行Docker-Compose启动Node Express服务失败求助
问题排查:Docker首次启动Node服务找不到/app/index.js,重启后正常
首次执行docker-compose up启动Node Express服务时,容器报错无法找到app/index.js文件(该文件本就不存在),此时dist文件夹正在创建。停止容器后再次启动,服务能正确指向app/dist/server.js并正常运行,求排查首次启动报错的原因。
相关配置信息
docker-compose.yml
version: '3.8' services: backend-service: build: context: . dockerfile: Dockerfile target: base container_name: backend-service image: backend-service restart: always environment: - NODE_ENV=dev - PORT=8095 ports: - '8095:8095' volumes: - ./:/app command: yarn dev
Dockerfile(测试时使用过ENTRYPOINT,忽略CMD,希望从docker-compose.yml中执行yarn dev命令)
FROM node:18.16.0-alpine as base COPY package*.json ./ COPY yarn.lock ./ RUN yarn install COPY . . RUN yarn build WORKDIR /app FROM node:18.16.0-alpine # ENTRYPOINT ["tail", "-f", "/dev/null"] EXPOSE 8095 CMD ["dist/server.js"]
package.json中的build脚本
"scripts": { "build": "npx tsc", "start": "node dist/server.js", "dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/server.js\"" }
首次启动时的错误信息
backend-service | 6:38:44 AM - Starting compilation in watch mode... backend-service | [0] backend-service | [1] node:internal/modules/cjs/loader:1078 backend-service | [1] throw err; backend-service | [1] ^ backend-service | [1] backend-service | [1] Error: Cannot find module '/app/index.js' backend-service | [1] at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15) backend-service | [1] at Module._load (node:internal/modules/cjs/loader:920:27) backend-service | [1] at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) backend-service | [1] at node:internal/main/run_main_module:23:47 { backend-service | [1] code: 'MODULE_NOT_FOUND', backend-service | [1] requireStack: [] backend-service | [1] } backend-service | [1] backend-service | backend-service | [1] Node.js v18.16.0 backend-service | backend-service | [0] backend-service | [0] 6:38:48 AM - Found 0 errors. Watching for file changes. backend-service | [1] backend-service | node:internal/modules/cjs/loader:1078 backend-service | [1] throw err; backend-service | [1] ^ backend-service | [1] backend-service | [1] Error: Cannot find module '/app/index.js' backend-service | [1] at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15) backend-service | [1] at Module._load (node:internal/modules/cjs/loader:920:27) backend-service | [1] at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) backend-service | [1] at node:internal/main/run_main_module:23:47 { backend-service | [1] code: 'MODULE_NOT_FOUND', backend-service | [1] requireStack: [] backend-service | [1] } backend-service | [1] backend-service | [1] Node.js v18.16.0
问题原因与解决方案
核心原因
- 挂载覆盖镜像文件:Dockerfile的
base阶段执行RUN yarn build生成了dist文件夹,但启动时通过volumes: - ./:/app把本地目录挂载到容器/app,直接覆盖了镜像中已有的dist。本地首次启动时还没生成dist,所以容器内也没有这个文件夹。 - 并行启动的时序问题:
yarn dev用concurrently同时启动tsc --watch和nodemon,两者并行执行——nodemon会立刻尝试加载dist/server.js,但此时tsc还没完成第一次编译,dist不存在。nodemon找不到指定文件时,会默认尝试启动项目根目录的index.js,这就是报错的来源。 - 重启正常的逻辑:首次启动时
tsc --watch已经完成了第一次编译,本地目录生成了dist。重启容器后,挂载的本地目录已有dist,nodemon能直接找到目标文件,因此正常运行。
修复方案
方案一:先完成首次编译再启动nodemon
修改package.json的dev脚本,让tsc先执行一次完整编译,再启动watch模式和nodemon:
"scripts": { "build": "npx tsc", "start": "node dist/server.js", "dev": "npx tsc && concurrently \"npx tsc --watch\" \"nodemon -q dist/server.js\"" }
确保首次启动时先生成dist文件夹,再启动nodemon,从根源避免文件找不到的问题。
方案二:移除本地目录挂载(适合纯容器化开发)
删除docker-compose.yml中的volumes: - ./:/app,容器会使用镜像构建时生成的dist文件夹,不会被本地目录覆盖。后续开发可通过修改代码后重新构建镜像更新,或只挂载源码目录而非整个/app。
方案三:给nodemon添加延迟启动
在nodemon命令中加入--delay参数,让它等待几秒再尝试启动,给tsc足够时间生成初始dist:
"scripts": { "build": "npx tsc", "start": "node dist/server.js", "dev": "concurrently \"npx tsc --watch\" \"nodemon -q --delay 2 dist/server.js\"" }
这种方式简单,但延迟时间需根据项目编译速度调整,稳定性稍差。
内容的提问来源于stack exchange,提问作者paperskyline
相关产品推荐
相关产品推荐

