Node app fails to connect to MongoDB, but only in Docker

Viewed 2032

I have two apps:

The two apps interact flawlessly when my node app is run natively. Now I've put it inside a Docker container and when I start both together with docker compose up, the backend can not connect to MongoDB.

This is an excerpt of the startup sequence:

mongodb_1   | 2018-11-10T22:22:52.481+0000 I NETWORK  [initandlisten] waiting for connections on port 27017
[...]
backend_1   | 2018-11-10T22:23:48.119Z 'MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]'

This is my docker-compose.yml:

version: '2'
services:

  mongodb:
    image: bitnami/mongodb:latest
    expose:
      - 27017
    environment:
      - ALLOW_EMPTY_PASSWORD=yes

  backend:
    build: ./backend
    environment:
      API_HOST: http://localhost:3000/
      APP_SERVER_PORT: 3000
    expose:
      - 3000
    volumes:
      - ./backend:/app/backend
    links:
      - mongodb
    depends_on:
      - mongodb

This is my node call to the DB:

mongoose.connect('mongodb://localhost:27017/groceryList', {
  useNewUrlParser: true
});

I skimmed about 15 Stackoverflow questions asking the same and I am not getting the cause:

  • It is not that MongoDB is not ready when my node app tries to connect. I wrapped my connection call into an auto reconnection function as described here and the error repeats endlessly. It is not just about the "first connect".
  • I can publish Port 27017 of the MongoDB container and happily connect with Robo3T. The DB is definitely working.
  • When I connect to mongodb://mongo:27017/groceryList instead, the same applies, only with the ENOTFOUND flag instead of ECONNREFUSED.

What am I missing?

  • Docker 18.06.1-ce
  • docker-compose 1.22.0
  • Mongoose 5.3.6
  • MongoDB 4.0.3
  • Node 11.1.0
  • macOS 10.14.1
2 Answers

Your mongodb service is named mongodb not mongo.

Try

mongoose.connect('mongodb://mongodb:27017/groceryList', {
  useNewUrlParser: true
});

The generic form is 'mongodb://mongoServiceName:27017/dbname', this uses docker's automatic dns resolution for containers within the same network.

And as you may already know from other questions/answers, within a container, the url is relative to itself, therefore since there not mongodb running inside the backend container, it can't connect to it.

It's not possible to use localhost:27017 into a container to communicate with other because the scope "localhost" is self refering (localhost:27017 will look for the port 27017 into the container backend - not in mongodb container)

Then, you ned to put or the service name (mongodb) or IP of your machine

Related