使用Docker连接Node.js与MongoDB时出现连接错误求助
Docker中Node.js连接MongoDB失败问题
错误信息
techworld-js-docker-demo-app-mongo-express-1 | 无法使用连接字符串连接到数据库: mongodb://admin:password@mongodb:27017/" techworld-js-docker-demo-app-mongo-express-1 | (node:7) UnhandledPromiseRejectionWarning: MongoNetworkError: 首次连接时无法连接到服务器 [mongodb:27017] [Error: connect ECONNREFUSED 172.19.0.3:27017 techworld-js-docker-demo-app-mongo-express-1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1144:16) { techworld-js-docker-demo-app-mongo-express-1 | name: 'MongoNetworkError' techworld-js-docker-demo-app-mongo-express-1 | }] techworld-js-docker-demo-app-mongo-express-1 | at Pool.<anonymous> (/node_modules/mongodb/lib/core/topologies/server.js:441:11) techworld-js-docker-demo-app-mongo-express-1 | at Pool.emit (events.js:314:20) techworld-js-docker-demo-app-mongo-express-1 | at /node_modules/mongodb/lib/core/connection/pool.js:564:14 techworld-js-docker-demo-app-mongo-express-1 | at /node_modules/mongodb/lib/core/connection/pool.js:1000:11 techworld-js-docker-demo-app-mongo-express-1 | at /node_modules/mongodb/lib/core/connection/connect.js:32:7 techworld-js-docker-demo-app-mongo-express-1 | at callback (/node_modules/mongodb/lib/core/connection/connect.js:300:5) techworld-js-docker-demo-app-mongo-express-1 | at Socket.<anonymous> (/node_modules/mongodb/lib/core/connection/connect.js:330:7) techworld-js-docker-demo-app-mongo-express-1 | at Object.onceWrapper (events.js:421:26) techworld-js-docker-demo-app-mongo-express-1 | at Socket.emit (events.js:314:20) techworld-js-docker-demo-app-mongo-express-1 | at emitErrorNT (internal/streams/destroy.js:92:8) techworld-js-docker-demo-app-mongo-express-1 | at emitErrorAndCloseNT (internal/streams/destroy.js:60:3) techworld-js-docker-demo-app-mongo-express-1 | at processTicksAndRejections (internal/process/task_queues.js:84:21) techworld-js-docker-demo-app-mongo-express-1 | (node:7) UnhandledPromiseRejectionWarning: 未处理的Promise拒绝。此错误要么是因为在没有catch块的async函数中抛出,要么是因为拒绝了一个未用.catch()处理的Promise。要在未处理的Promise拒绝时终止Node进程,请使用CLI标志`--unhandled-rejections=strict`。(拒绝id: 1)
当前配置
docker-compose.yaml
version: '3' services: my-app: image: nihalchandra/myapp:4.0 ports: - 3000:3000 mongodb: image: mongo restart: always ports: - 27017:27017 environment: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=password volumes: - mongo-data:/data/db mongo-express: image: mongo-express restart: always # 修复mongo-express启动时mongodb未就绪导致的MongoNetworkError ports: - 8081:8081 environment: - ME_CONFIG_MONGODB_ADMINUSERNAME=admin - ME_CONFIG_MONGODB_ADMINPASSWORD=password - ME_CONFIG_MONGODB_SERVER=mongodb volumes: mongo-data: driver: local
server.js中的连接配置
let mongoUrlLocal = "mongodb://admin:password@localhost:27017"; let mongoUrlDocker = "mongodb://admin:password@mongodb";
解决方案
修正连接字符串,指定认证库:
root用户的认证需要指定authSource=admin,Docker环境的连接字符串应改为:let mongoUrlDocker = "mongodb://admin:password@mongodb:27017/?authSource=admin";确保my-app使用Docker环境的连接地址:
在docker-compose.yaml的my-app服务中添加环境变量,明确告知应用使用Docker配置:my-app: image: nihalchandra/myapp:4.0 ports: - 3000:3000 environment: - NODE_ENV=docker然后在
server.js中根据环境变量自动选择连接地址:const mongoUrl = process.env.NODE_ENV === 'docker' ? "mongodb://admin:password@mongodb:27017/?authSource=admin" : "mongodb://admin:password@localhost:27017/?authSource=admin";添加服务依赖与重启策略:
让my-app在mongodb启动后再启动,并添加重启策略,避免因MongoDB未就绪导致的连接失败:my-app: image: nihalchandra/myapp:4.0 ports: - 3000:3000 environment: - NODE_ENV=docker restart: always depends_on: - mongodb注意:
depends_on仅保证启动顺序,不保证MongoDB完全就绪,建议在应用的数据库连接逻辑中添加重试机制,比如使用MongoDB驱动的重试参数或自定义重试逻辑。检查网络连通性:
进入my-app容器,测试与mongodb服务的连通性:docker exec -it techworld-js-docker-demo-app-my-app-1 ping mongodb如果ping不通,检查是否所有服务都在同一个Docker网络中(默认docker-compose会创建默认网络,所有服务自动加入)。
内容的提问来源于stack exchange,提问作者Nihal_20
相关产品推荐
相关产品推荐

