You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Node服务server.js读不到环境变量且Mongo连接报错

问题根因

核心问题出在启动脚本的写法错误,导致server.js根本没有在Docker容器内部运行,你实际访问到的5000端口服务是运行在Docker外部的宿主机上的,因此引发两个连锁问题:

  • 宿主机上运行的Node进程没有注入docker-compose为test-app容器配置的MONGO_USER等环境变量,读取结果自然为undefined
  • 宿主机进程不在Docker Compose创建的内部虚拟网络中,无法通过Docker内置DNS解析到mongo这个服务域名,因此抛出MongooseServerSelectionError: getaddrinfo ENOTFOUND mongo错误

你在package.json里写的启动命令是:

"scripts": {
  "start": "nodemon index.js && nodemon server.js",
  "dev": "nodemon index.js && nodemon server.js"
}

Shell语法中&&是顺序执行符,只有前一个命令执行完成、正常退出后才会执行后一个命令。而nodemon index.js是常驻进程,启动后会一直监听端口和文件变化,永远不会主动退出,因此后面的nodemon server.js永远不会在容器内被执行。你之所以能看到两个服务Socket通信正常,是因为你大概率在本地宿主机上手动启动了server.js,连的是容器暴露出来的3000端口服务。

另外你的配置还有两个明显问题:

  1. docker-compose.yml中的mongo服务没有指定镜像,缺少image: mongo配置,正常情况下这个服务是无法启动的
  2. 单容器跑多个常驻进程不符合Docker最佳实践,进程异常退出时很难被Docker感知到,也不方便做资源隔离和日志收集

排查解决步骤

快速修复(开发环境临时使用)

修改package.json的启动脚本,把&&换成&,让两个进程同时在后台启动:

"scripts": {
  "start": "nodemon index.js & nodemon server.js",
  "dev": "nodemon index.js & nodemon server.js"
}

修改后先停掉你之前在宿主机上手动启动的server.js进程避免端口冲突,再执行docker-compose up --build启动,启动后可以通过以下方式验证:

  • 执行docker exec -it <你的test-app容器ID> ps aux,能看到两个nodemon/node进程分别对应index.js和server.js
  • 执行docker exec -it <你的test-app容器ID> env,能看到MONGO_USER、MONGO_PASSWORD环境变量已正常注入
  • 此时server.js运行在容器内部,和mongo服务在同一个Docker网络,可正常解析mongo域名、连接数据库

规范修复(推荐方案)

遵循Docker单容器单进程的最佳实践,把两个Node服务拆成docker-compose里的两个独立服务,修改后的docker-compose.yml示例:

version: "3"
services:
  test-app-index:
    build:
      context: .
      args:
        NODE_ENV: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - MONGO_USER=test_admin
      - MONGO_PASSWORD=9293
    command: npx nodemon index.js
    ports:
      - "3000:3000"
  test-app-server:
    build:
      context: .
      args:
        NODE_ENV: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - MONGO_USER=test_admin
      - MONGO_PASSWORD=9293
    command: npx nodemon server.js
    ports:
      - "5000:5000"
  mongo:
    image: mongo # 补全缺失的镜像配置
    environment:
      - MONGO_INITDB_ROOT_USERNAME=test_admin
      - MONGO_INITDB_ROOT_PASSWORD=9293
    volumes:
      - mongo-data:/data/db # 增加数据卷持久化Mongo数据,避免容器重启数据丢失
  mailhog:
    image: mailhog/mailhog
    logging:
      driver: 'none'
    ports:
      - 1025:1025
      - 8025:8025

volumes:
  mongo-data:

这种方式下两个Node服务都在同一个Docker内部网络,都能正常读取环境变量、解析mongo服务域名,而且两个进程独立隔离,一个崩溃不会影响另一个,日志也可以单独查看。


内容的提问来源于stack exchange,提问作者IGentlich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 20:06:39