Docker环境下Express容器无法连接MongoDB的问题求助
Docker容器连接问题:Express无法连接MongoDB
问题描述
Docker新手搭建带用户登录功能的网站时,遇到Express服务器容器无法与MongoDB容器建立连接的问题,报错MongooseServerSelectionError: getaddrinfo ENOTFOUND mongodb。目前mongo-express管理页面可正常访问,但Express与MongoDB的连接始终失败。
相关配置与日志
docker-compose.yaml
services: express: container_name: video-express image: video-express:latest build: context: ./express dockerfile: Dockerfile.express ports: - "13000:3000" volumes: - video_express_node:/app/node_modules - ./express:/app tty: true stdin_open: true depends_on: - mongo networks: - default mongo: image: mongo:latest restart: always ports: - "27018:27017" environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: password MONGO_INITDB_DATABASE: q-cards-db volumes: - ./data/db:/database networks: - default - mongo-express mongo_express: image: mongo-express restart: always ports: - "8081:8081" environment: ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: password ME_CONFIG_MONGODB_SERVER: mongo # ME_CONFIG_BASICAUTH_USERNAME: admin # ME_CONFIG_BASICAUTH_PASSWORD: Password1 depends_on: - mongo networks: - mongo-express dev: container_name: video-dev image: video-dev:latest build: context: . dockerfile: Dockerfile ports: - "15173:5173" volumes: - video_dev_node_modules:/app/node_modules - .:/app depends_on: - express tty: true stdin_open: true networks: - default networks: default: driver: bridge mongo-express: driver: bridge volumes: video_dev_node_modules: video_express_node:
server.js连接代码
mongoose.connect("mongodb://root:pass@mongodb:27017/videoUserDB", { useNewUrlParser: true });
错误日志
(node:7) [MONGODB DRIVER] Warning: Current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor. video-management-mongo_express-1 | Could not connect to database using connectionString: mongodb://root:password@mongo:27017/" video-management-mongo_express-1 | (node:7) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [mongo:27017] on first connect [Error: connect ECONNREFUSED 172.19.0.2:27017 video-management-mongo_express-1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) { video-management-mongo_express-1 | name: 'MongoNetworkError' video-management-mongo_express-1 | }] video-management-mongo_express-1 | at Pool.<anonymous> (/node_modules/mongodb/lib/core/topologies/server.js:441:11) video-management-mongo_express-1 | Mongo Express server listening at http://0.0.0.0:8081 video-management-mongo_express-1 | Server is open to allow connections from anyone (0.0.0.0) video-express | /app/node_modules/mongoose/lib/connection.js:824 video-express | const serverSelectionError = new ServerSelectionError(); video-express | ^ video-express | video-express | MongooseServerSelectionError: getaddrinfo ENOTFOUND mongodb video-express | at Connection.openUri (/app/node_modules/mongoose/lib/connection.js:824:32) video-express | at /app/node_modules/mongoose/lib/index.js:381:10 video-express | at /app/node_modules/mongoose/lib/helpers/promiseOrCallback.js:41:5 video-express | at new Promise (<anonymous>) video-express | at promiseOrCallback (/app/node_modules/mongoose/lib/helpers/promiseOrCallback.js:40:10) video-express | at Mongoose._promiseOrCallback (/app/node_modules/mongoose/lib/index.js:1234:10) video-express | at Mongoose.connect (/app/node_modules/mongoose/lib/index.js:380:20) video-express | at Object.<anonymous> (/app/server.js:50:10) video-express | at Module._compile (node:internal/modules/cjs/loader:1159:14) video-express | at Module._extensions..js (node:internal/modules/cjs/loader:1213:10) { video-express | reason: TopologyDescription { video-express | type: 'Unknown', video-express | servers: Map(1) { video-express | 'mongodb:27017' => ServerDescription { video-express | address: 'mongodb:27017', video-express | type: 'Unknown',
问题定位
- 主机名错误:Express连接字符串使用的主机名是
mongodb,但docker-compose中MongoDB服务的名称为mongo,容器间通信必须以服务名作为主机名。 - 密码不匹配:连接字符串中的密码是
pass,但docker-compose配置的MongoDB root密码是password,认证信息不一致导致连接失败。 - 数据库名称不一致:docker-compose初始化的数据库是
q-cards-db,但连接字符串指定的是videoUserDB,若该库未提前创建,需确认MongoDB是否允许自动创建数据库。 - 缺少必要连接选项:MongoDB驱动提示需添加
useUnifiedTopology: true选项,否则会有弃用警告,也可能影响连接稳定性。
修复步骤
1. 修改Express连接字符串
将主机名改为mongo,密码改为password,同时添加useUnifiedTopology: true选项:
mongoose.connect("mongodb://root:password@mongo:27017/videoUserDB", { useNewUrlParser: true, useUnifiedTopology: true });
若要使用初始化的q-cards-db,可将连接字符串中的videoUserDB替换为q-cards-db。
2. (可选)添加MongoDB健康检查
depends_on仅保证容器启动顺序,不等待MongoDB完全就绪。可在docker-compose的mongo服务中添加健康检查,确保Express在MongoDB就绪后再尝试连接:
mongo: # 其他配置保持不变 healthcheck: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"] interval: 10s timeout: 5s retries: 5
同时修改express服务的depends_on配置,等待MongoDB健康检查通过:
express: # 其他配置保持不变 depends_on: mongo: condition: service_healthy
3. 重启容器
执行以下命令重启所有容器,使配置生效:
docker-compose down docker-compose up --build
内容的提问来源于stack exchange,提问作者koji tanaka
相关产品推荐
相关产品推荐

