skip to Main Content

I am doing a REST API with Express and MongoDB. Everything works perfectly locally. I want to dockerize the database and the backend using Docker Compose.

The Mongo Docker works perfectly, but the backend fails to connect to it. It keeps throwing me this error:

/backend/node_modules/mongoose/lib/connection.js:797

  const serverSelectionError = new ServerSelectionError();

                               ^


MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017

    at NativeConnection.Connection.openUri (/backend/node_modules/mongoose/lib/connection.js:797:32)

    at /backend/node_modules/mongoose/lib/index.js:341:10

    at /backend/node_modules/mongoose/lib/helpers/promiseOrCallback.js:32:5

    at new Promise (<anonymous>)

    at promiseOrCallback (/backend/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:10)

    at Mongoose._promiseOrCallback (/backend/node_modules/mongoose/lib/index.js:1167:10)

    at Mongoose.connect (/backend/node_modules/mongoose/lib/index.js:340:20)

    at Object.<anonymous> (/backend/index.js:11:3)

    at Module._compile (node:internal/modules/cjs/loader:1097:14)

    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10) {

  reason: TopologyDescription {

    type: 'Unknown',

    servers: Map(1) {

      'localhost:27017' => ServerDescription {

        _hostAddress: HostAddress { isIPv6: false, host: 'localhost', port: 27017 },

        address: 'localhost:27017',

        type: 'Unknown',

        hosts: [],

        passives: [],

        arbiters: [],

        tags: {},

        minWireVersion: 0,

        maxWireVersion: 0,

        roundTripTime: -1,

        lastUpdateTime: 14312460,

        lastWriteDate: 0,

        error: MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017

            at connectionFailureError (/backend/node_modules/mongodb/lib/cmap/connect.js:293:20)

            at Socket.<anonymous> (/backend/node_modules/mongodb/lib/cmap/connect.js:267:22)

            at Object.onceWrapper (node:events:510:26)

            at Socket.emit (node:events:390:28)

            at emitErrorNT (node:internal/streams/destroy:164:8)

            at emitErrorCloseNT (node:internal/streams/destroy:129:3)

            at processTicksAndRejections (node:internal/process/task_queues:83:21)

      }

    },

    stale: false,

    compatible: true,

    heartbeatFrequencyMS: 10000,

    localThresholdMS: 15,

    logicalSessionTimeoutMinutes: undefined

  }

}

I’ve read online that the issue could be that I shouldn’t connect to localhost but to the MongoDB container.

I attach the files:

docker-compose.yml

version: '3.8'

services:
    data:
      container_name: data
      image: mongo
      ports:
        - 27017:27017
      volumes:
        - ./data/db:/data/db
    
    backend:
      container_name: backend
      depends_on:
        - data
      build: ./backend
      ports:
        - 5000:5000
      environment:
        - DB_HOST=data
        - DB_NAME=${DB_NAME?:}
        - DB_PORT=${DB_PORT?:}

/backend/Dockerfile

# pull official base image
FROM node:latest

# set working directory
WORKDIR /backend

EXPOSE 5000

ENV PORT=5000
ENV HOST=0.0.0.0

# install backend dependencies
COPY package*.json ./
RUN npm ci --only-production

# add backend
COPY . .

# start backend
CMD npm start

/backend/index.js

const express = require("express")
const mongoose = require("mongoose")
const property = require("./routes/property-router")
const properties = require("./routes/properties-router")
const statistics = require("./routes/statistics-router")
const bodyParser = require("body-parser")
const dbConfig = require("./config/db.config")
require("dotenv").config();
var cors = require("cors")


// Connect to MongoDB database
mongoose
    .connect(dbConfig.url, { useNewUrlParser: true })
    .then(() => {
        const app = express()

        app.use(cors())

        app.use(bodyParser.text({ type: '*/*'}))

        app.use("/api", statistics)
        app.use("/api", properties)
        app.use("/api", property)

        const PORT = dbConfig.port || 5000;

        app.listen(PORT, () => {
            console.log(`Server is running on port ${PORT}.`);
        });
    })

/backend/config/db.config.js

require('dotenv').config();

const {
    DB_HOST,
    DB_PORT,
    DB_NAME,
    PORT,
  } = process.env;
  
  module.exports = {
    url: `mongodb://${DB_HOST}:${DB_PORT}/${DB_NAME}`,
    port: PORT
  };

/backend/.env

PORT=5000
HOST=localhost

DB_HOST=localhost
DB_NAME=propertyDB
DB_PORT=27017

Running the backend locally I can connect to the MongoDB Docker without any issues. By leaving only the data in the Docker Compose file and running node index.js.

What am I doing wrong?

Edit

I have even changed the URL from index.js to a random URL and still remains the same error and tries to connect to 127.0.0.1:27017.

.connect("randomurl.com", { useNewUrlParser: true })

2

Answers


  1. Chosen as BEST ANSWER

    The issue is that when you run the docker compose a new image is created and stored. So every time you run the same container the same image will be executed. What you have to do is the following:

    For the first step, you should first shut down any running docker-compose configurations:

    $ docker-compose down
    

    You can use the following command to verify that nothing is left running:

    $ docker ps --all
    

    To remove locally build images, first list all of the images cached locally, then remove anything that was built locally:

    $ docker images
    

    Then remove the image that is giving you issues.

    $ docker rmi <image_name>
    

    This solved the issue.


  2. Docker containers behave like nodes in a network. Unless you tell it not to, Docker Compose creates a virtual network, and assigns DNS names inside that network corresponding to the service names in the docker-compose.yml file. The values in .env overwrite the environment variables in docker-compose.yml.

    You can remove (i.e. not copy) the .env file and set the values using environment variables by adding .env to .dockerignore.

    Alternatively, you can change

    DB_HOST=localhost
    

    to

    DB_HOST=data
    

    in .env. The .env file should contain

    PORT=5000
    HOST=localhost
    
    DB_HOST=data
    DB_NAME=propertyDB
    DB_PORT=27017
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search