skip to Main Content

I made 3 docker containers from 2 images in this repo and 1 using MongoDB public image. I turned ON all three containers using sudo docker-compose -f docker-compose.yaml up

docker-compose.yaml is:

version: '3'
services:
  frontend:
    image: samar080301/mern-frontend:1.0
    ports:
      - 3000:3000
  backend:  
    image: samar080301/mern-backend:1.0
    ports:
      - 5000:5000
  mongodb:
    image: mongo:latest
    ports:
      - 27017:27017

But the MongoDB couldn’t connect with the node server and gave this error:

backend_1   | > [email protected] start /home/app
backend_1   | > node server.js
backend_1   | 
backend_1   | (node:18) DeprecationWarning: 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.
backend_1   | (Use `node --trace-deprecation ...` to show where the warning was created)
backend_1   | App running on port 5000
backend_1   | Error with the database! MongoNetworkError: failed to connect to server [localhost:27017] on first connect [Error: connect ECONNREFUSED 127.0.0.1:27017
backend_1   |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) {
backend_1   |   name: 'MongoNetworkError'
backend_1   | }]
backend_1   |     at Pool.<anonymous> (/home/app/node_modules/mongodb/lib/core/topologies/server.js:438:11)
backend_1   |     at Pool.emit (events.js:315:20)
backend_1   |     at /home/app/node_modules/mongodb/lib/core/connection/pool.js:562:14
backend_1   |     at /home/app/node_modules/mongodb/lib/core/connection/pool.js:995:11
backend_1   |     at /home/app/node_modules/mongodb/lib/core/connection/connect.js:32:7
backend_1   |     at callback (/home/app/node_modules/mongodb/lib/core/connection/connect.js:280:5)
backend_1   |     at Socket.<anonymous> (/home/app/node_modules/mongodb/lib/core/connection/connect.js:310:7)
backend_1   |     at Object.onceWrapper (events.js:422:26)
backend_1   |     at Socket.emit (events.js:315:20)
backend_1   |     at emitErrorNT (internal/streams/destroy.js:84:8)
backend_1   |     at processTicksAndRejections (internal/process/task_queues.js:84:21)
backend_1   | (node:18) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [localhost:27017] on first connect [Error: connect ECONNREFUSED 127.0.0.1:27017
backend_1   |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) {
backend_1   |   name: 'MongoNetworkError'
backend_1   | }]

Code of backend/db.js:

const mongoose = require('mongoose');
// Allow Promises
mongoose.Promise = global.Promise;
// Connection
mongoose.connect('mongodb://localhost:27017/db_test', { useNewUrlParser: true });
// Validation
mongoose.connection
  .once('open', () => console.log('Connected to the database!'))
  .on('error', err => console.log('Error with the database!', err));

Terminal Output of docker inspect mongodb:
enter image description here

Terminal output after adding the mongo uri as environment variable:

backend_1   | App running on port 5000
backend_1   | (node:19) UnhandledPromiseRejectionWarning: MongooseError: The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.
backend_1   | (node:19) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

New error:

backend_1   | Error with the database! MongoNetworkError: failed to connect to server [merncrudapp_mongodb_1:27017] on first connect [Error: connect ECONNREFUSED 172.23.0.3:27017
backend_1   |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16) {
backend_1   |   name: 'MongoNetworkError'
backend_1   | }]

3

Answers


  1. Try to connect not using localhost but a container name. So for example, if you want to connect to MongoDB from another container (in the same docker network) you can use mongodb:27017.
    It should work.

    Login or Signup to reply.
  2. When you run docker-compose up, the following happens:

    1. A network called MernCrudApp(takes the default name of the directory) is created.
    2. A container is created using the frontend‘s configuration. It joins the network MernCrudApp under the name frontend.
    3. A container is created using the backend‘s configuration. It joins the network MernCrudApp under the name backend.
    4. A container is created using mongodb’s configuration. It joins the network MernCrudApp under the name mongodb.

    now if you use mongodb://localhost:27017/db_test to connect to the db, the node app will look for MongoDB in the backend container which you will get a connection error since it does not exist.

    To remedy this, change the MongoDB connection string to mongodb://mongodb:27017/db_test so that it

    Aditional comments
    I would recommend the following to help solve some problems you might face in the future using the current configuration.

    1. Add the connection string as an environment variable. This will make it easier for you to change the DB instances without rebuilding the container.
    2. Since the backend application depends on the database add depend_on on the docker-compose files so that the MongoDB container starts before the backend container
    Login or Signup to reply.
  3. Modify your backend/db.js code.

    Your are getting error because when you mention ‘localhost‘ in code your container is trying to connect to backend container on port 2017 which not in use.

    // Connection
    //mongodb is a container name of mongo image
    mongoose.connect('mongodb://mongodb:27017/db_test', { useNewUrlParser: true });
    

    Pro Tip –
    1)If you are in same docker network then use hostname or Docker Container Name to communicate/Link with each other.

    2)Never use container IP address in code if IP’s are not assign manually. Whenever you restart container it may change.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search