skip to Main Content

I have a project with this directory structure:

- other-service/
- my-service/
   src/
   Dockerfile
   .env
docker-compose
.env

I have defined my mongoDB container & service container in a docker-compose.yml file like below:

version: "3"
services:
  my-service:
    depends_on:
      - mongodb
    env_file: ./my-service/.env
    container_name: my-service
    build: ./my-service
    environment:
      - DB_HOST=$DB_HOST
      - DB_USER=$DB_USER
      - DB_PASSWORD=$DB_PASSWORD
      - DB_NAME=$DB_NAME
      - DB_PORT=$DB_PORT
    ports:
      - "3002:3002"

  mongodb:
    image: mongo:latest
    container_name: my-mongodb
    env_file: ./.env
    environment:
      MONGO_INITDB_ROOT_USERNAME: $DB_USER
      MONGO_INITDB_ROOT_PASSWORD: $DB_PASSWORD
    ports:
      - $DB_PORT:$DB_PORT
    volumes:
      - db_vol:/data/db

volumes:
  db_vol:

The my-service/.env file looks like this:

DB_HOST=mongodb
DB_USER=root
DB_PASSWORD=pass123
DB_NAME=my_db
DB_PORT=27017
...

The root level .env looks like this (basically the same content as my-service/.env for the DB part):

#used by compose
DB_HOST=mongodb
DB_USER=root
DB_PASSWORD=pass123
DB_NAME=my_db
DB_PORT=27017

my-service tries to connect to mongoDB with this code:

 const dbUri=`mongodb://${process.env['DB_USER']}:${process.env['DB_PASSWORD']}@${process.env['DB_HOST']}:${process.env['DB_PORT']}/${process.env['DB_NAME']}`

 console.log(`DB connect to: ${dbUri}`);
 await mongoose.connect(dbUri, {
            useNewUrlParser: true,
            useUnifiedTopology: true,
            useCreateIndex: true
        });

After I run docker-compose build & docker-compose up -d. The my-mongodb container is up and running. But my-service is not. I checked the container log, it shows:

DB connect to: mongodb://root:pass123@mongodb:27017/my_db
...
DatabaseConnError: Database connection failure. undefined
  ...
  statusCode: 500,
  msg: 'Database connection failure'
}

Node.js v19.2.0

I feel it is because both containers are on the same Docker bridge network, the database URI I defined might not correct? But I am not sure. Could someone please guide me where could be wrong in my case?

=== UPDATE on 8th of December2022 ===

I dug deeper of my problem, it turned out the problem is actually an AuthenticationError, full error log is below:

Database connection failure. {"ok":0,"code":18,"codeName":"AuthenticationFailed","name":"MongoError"}

It is the same issue @jeeves’ answer below has mentioned, then I tried adding ?authSource=admin like @jeeves suggested:

DB connect to: mongodb://root:pass123@mongodb:27017/my_db?authSource=admin

but I still get the authentication error. Why?

2

Answers


  1. you might need a healthcheck for mongodb.

    version: "3"
    services:
      my-service:
        depends_on:
          mongodb:
            condition: service_healthy
        env_file: ./my-service/.env
        container_name: my-service
        build: ./my-service
        environment:
          - DB_HOST=$DB_HOST
          - DB_USER=$DB_USER
          - DB_PASSWORD=$DB_PASSWORD
          - DB_NAME=$DB_NAME
          - DB_PORT=$DB_PORT
        ports:
          - "3002:3002"
    
      mongodb:
        image: mongo:latest
        container_name: my-mongodb
        env_file: ./.env
        environment:
          MONGO_INITDB_ROOT_USERNAME: $DB_USER
          MONGO_INITDB_ROOT_PASSWORD: $DB_PASSWORD
        ports:
          - $DB_PORT:$DB_PORT
        volumes:
          - db_vol:/data/db
        healthcheck:
          test:  echo 'db.runCommand("ping").ok' | mongosh localhost:$DB_PORT/test --quiet
          interval: 10s
          timeout: 10s
          retries: 5
          start_period: 10s      
    
    volumes:
      db_vol:
    

    Similar: mongodb and mongo-express not connecting with docker-compose

    Login or Signup to reply.
  2. I’m not sure where the problem here is.
    I certainly had a few issues authenticating with the DB but I believe that that is an issue with the database itself (and my lack of understanding of it ;)) and not a docker-compose/ networking problem.

    Here is a stripped back (but working) version.

    Directory structure

    enter image description here

    docker-compose file

    version: "3"
    services:
      my-service:
        depends_on:
          - mongodb
        container_name: my-service
        build: ./my-service
        environment:
          - DB_HOST=mongodb
          - DB_USER=root
          - DB_PASSWORD=password123
          - DB_NAME=test
          - DB_PORT=27017
        ports:
          - "3002:3002"
    
      mongodb:
        image: mongo:latest
        environment:
          MONGO_INITDB_ROOT_USERNAME: root
          MONGO_INITDB_ROOT_PASSWORD: password123
        ports: 
          - "27017:27017"
    

    Dockerfile

    FROM node:19
    
    WORKDIR /usr/src/app
    COPY . .
    RUN npm install
    USER node
    CMD ["node", "index.js"]
    

    And my index.js

    Note: added following query param ?authSource=admin to connection string.

    const mongoose = require('mongoose');
    console.log(process.env);
    
    const dbUri=`mongodb://${process.env['DB_USER']}:${process.env['DB_PASSWORD']}@${process.env['DB_HOST']}:${process.env['DB_PORT']}/${process.env['DB_NAME']}?authSource=admin`
    
    console.log(dbUri, {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useCreateIndex: true
    });
    
    mongoose.connect(dbUri).then(() => console.log('is connected'))
           .catch((error) => console.log(error));
    

    Then execute following:

    $ cd demo
    $ docker-compose build
    $ docker-compose up mongodb
    $ docker-compose up my-service
    

    Output from my-service:

    $ docker-compose up my-service
    demo_mongodb_1 is up-to-date
    Recreating my-service ... done
    Attaching to my-service
    my-service    | {
    my-service    |   NODE_VERSION: '19.2.0',
    my-service    |   HOSTNAME: 'ea324ba32274',
    my-service    |   DB_PORT: '27017',
    my-service    |   YARN_VERSION: '1.22.19',
    my-service    |   HOME: '/home/node',
    my-service    |   DB_NAME: 'test',
    my-service    |   PATH: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
    my-service    |   DB_PASSWORD: 'password123',
    my-service    |   PWD: '/usr/src/app',
    my-service    |   DB_HOST: 'mongodb',
    my-service    |   DB_USER: 'root'
    my-service    | }
    my-service    | mongodb://root:password123@mongodb:27017/test?authSource=admin
    my-service    | (node:1) [MONGOOSE] DeprecationWarning: Mongoose: the `strictQuery` option will be switched back to `false` by default in Mongoose 7. Use `mongoose.set('strictQuery', false);` if you want to prepare for this change. Or use `mongoose.set('strictQuery', true);` to suppress this warning.
    my-service    | (Use `node --trace-deprecation ...` to show where the warning was created)
    my-service    | is connected
    

    The additional query string is doing nothing for connectivity between containers. I was getting an authentication error when connecting – but that still meant containers had connectivity.

    Hope this helps

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