I am using mongoDB with and NodeJS backend. The Problem is I am getting the following error

node:16) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]

This is my docker-compose

version: '3.4'

services:
  db:
    image: mongo:latest
    ports:
      - '27017:27017'

  rest-api-node:
    build: .
    ports:
      - '5000:5000'
    links:
      - db
    restart: on-failure

I have tried with depends_on as well , was not working.

On backend I am mongoose as a middleware to communicate with DB. this is the part of my index.js

mongoose.Promise = global.Promise
mongoose.connect('mongodb://localhost/demo')
app.listen(port, () => console.log("live"))

I have tried using promise as well , no change though. Please Help me out. Thanks in advance

complete error log

at Pool. (/app/node_modules/mongodb-core/lib/topologies/server.js:505:11) rest-api-node_1 | at Pool.emit (events.js:180:13) rest-api-node_1 | at Connection. (/app/node_modules/mongodb-core/lib/connection/pool.js:329:12) rest-api-node_1 | at Object.onceWrapper (events.js:272:13) rest-api-node_1 | at Connection.emit (events.js:180:13) rest-api-node_1 | at Socket. (/app/node_modules/mongodb-core/lib/connection/connection.js:245:50) rest-api-node_1 | at Object.onceWrapper (events.js:272:13) rest-api-node_1 | at Socket.emit (events.js:180:13) rest-api-node_1 | at emitErrorNT (internal/streams/destroy.js:64:8) rest-api-node_1 | at process._tickCallback (internal/process/next_tick.js:178:19) rest-api-node_1 | name: 'MongoNetworkError', rest-api-node_1 |
message: 'failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]' }

Solution 1

By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.

According to your docker-compose.yaml file you can access you mongo container on 127.0.0.1:27017 only from host machine. In order to access it from NodeJS backend container you should use db:27017.

Solution 2

I have the same problem, other solutions not work for me but I did that this way

Note :

for mongo URI you must use your MongoDB service name instead 127.0.0.1 or localhost

for example, in below docker-compose file my mongo service name is mongodb-myapp and I change URI like this mongodb://mongodb-myapp:27017/myapp and it works for me


services:
  boilerplate-api-app:
    build: .
    environment:
      - MONGO_URI=mongodb://mongodb-myapp:27017/myapp
    volumes:
      - .:/app
    ports:
      - "5000:5000"
    depends_on:
      - mongodb-myapp

 mongodb-myapp:
    image: mongo
    ports:
      - "27017:27017"

Solution 3

I was also stuck on this for hours! Setting db:27017 in the connection string and restart: always on the rest-api-node makes sure that you connect to the correct IP and makes sure that the node server keeps on trying to connect to your db. This worked for me!

Solution 4

docker-compose.yaml

version: "3"
services:
  node-app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - PORT=3000
  mongo:
    image: mongo
    environment:
      - MONGO_INITDB_ROOT_USERNAME=imran
      - MONGO_INITDB_ROOT_PASSWORD=test_password
    volumes:
      - mongo-db:/data/db

volumes:
  mongo-db:

The above code is the docker-compose.yaml file and the service name for the MongoDB is 'mongo'. You don't have to manually insert the IP address of the container. Instead of that just insert the service name in the MongoDB URI like this sample code given below:

const express = require("express");
const mongoose = require("mongoose");

const app = express();
mongoose
  .connect("mongodb://imran:[email protected]:27017/?authSource=admin")
  .then(() => {
    console.log("Successfully connected to the DB");
  })
  .catch((e) => {
    console.log(e);
  });

const port = process.env.PORT || 3000;

// routes
app.get("/", (req, res) => {
  res.send("<h1>Running on Container!</h1>");
});

app.listen(port, () => console.log(`listening on port ${port}`));