Node.js容器连接MongoDB容器超时(MongoServerSelectionError)求助
问题描述
使用如下docker-compose.yaml部署Node.js和MongoDB服务:
version: '3.8' networks: mongodb: name: mongodb driver: bridge host: name: host driver: host services: nodejs-server: networks: - mongodb - host build: context: ./api network: host ports: - "8000:8000" container_name: node-api volumes: - ./api:/usr/src/app/api - /usr/src/app/api/node_modules mongodb: image: mongo networks: mongodb: container_name: mongodb ports: - 27017:27017 restart: always environment: MONGO_INITDB_DATABASE: Demo MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: password
Express服务器index.js中的MongoDB连接代码:
const { MongoClient } = require('mongodb'); const mongoDB = 'mongodb://admin:password@mongodb:27017'; const mongoClient = new MongoClient(mongoDB);
app.get('/mongo', async (req, res) => { console.log('connecting...'); await mongoClient.connect(); console.log('connected...'); const database = mongoClient.db('insertDB'); const haiku = database.collection('haiku'); });
运行应用时,程序卡在await mongoClient.connect();,抛出异常:
MongoServerSelectionError: Server selection timed out after 30000 ms
但进入nodejs-server容器执行ping mongodb能正常连通:
/usr/src/app/api # ping mongodb PING mongodb (172.21.0.2): 56 data bytes 64 bytes from 172.21.0.2: seq=0 ttl=64 time=0.146 ms 64 bytes from 172.21.0.2: seq=1 ttl=64 time=0.122 ms 64 bytes from 172.21.0.2: seq=2 ttl=64 time=0.199 ms
问题排查与解决方案
核心原因:多网络挂载的冲突
你的nodejs-server容器同时挂载了host网络和mongodb自定义bridge网络。当容器使用host网络时,会直接复用宿主机的网络栈,此时容器内的DNS解析优先走宿主机的DNS服务,而不是Docker自定义网络的内部DNS——这就导致MongoDB驱动无法通过容器名mongodb正确找到对应的服务实例,虽然ICMP协议的ping能通,但TCP连接无法正常建立。
具体修复步骤
移除host网络依赖
修改docker-compose.yaml,给nodejs-server只保留mongodb网络,同时删掉无用的host网络定义:version: '3.8' networks: mongodb: name: mongodb driver: bridge services: nodejs-server: networks: - mongodb build: context: ./api network: host ports: - "8000:8000" container_name: node-api volumes: - ./api:/usr/src/app/api - /usr/src/app/api/node_modules mongodb: image: mongo networks: mongodb: container_name: mongodb ports: - 27017:27017 restart: always environment: MONGO_INITDB_DATABASE: Demo MONGO_INITDB_ROOT_USERNAME: admin MONGO_INITDB_ROOT_PASSWORD: password完善MongoDB连接字符串
因为启用了root用户,连接字符串需要指定认证数据库为admin,否则驱动无法完成身份校验:const mongoDB = 'mongodb://admin:password@mongodb:27017/?authSource=admin';添加错误捕获逻辑
在接口中加入错误处理,方便后续排查问题:app.get('/mongo', async (req, res) => { console.log('connecting...'); try { await mongoClient.connect(); console.log('connected...'); const database = mongoClient.db('insertDB'); const haiku = database.collection('haiku'); res.send('MongoDB连接成功'); } catch (err) { console.error('连接失败:', err); res.status(500).send('MongoDB连接失败'); } });重启服务
执行命令重建并启动容器:docker-compose down docker-compose up --build
内容的提问来源于stack exchange,提问作者Teoman shipahi
相关产品推荐
相关产品推荐

