Unable to connect ot local mongoDb docker database

Viewed 249

I have a problem connecting to a mongoDb from my dotnet core 3.1 application. Both the mongoDb and the API application is running inside container. Every container can be reached from the localhost and they are using the default docker network settings.

My mongoDb docker-compose file

version: "3.4"

services:
  mongoDatabase:
    restart: always
    image: mongo:latest
    environment:
      - MONGO_INITDB_ROOT_USERNAME=root
      - MONGO_INITDB_ROOT_PASSWORD=rootPassword
    volumes:
      - ./mongoDatabase:/data/db
    ports:
      - "27017:27017"

My application docker-compose file

writer.api:
    image: ${DOCKER_REGISTRY-}writerapi
    build:
      context: .
      dockerfile: Services/Writer/Writer.API/Dockerfile
    environment:
        - MONGODB_CONNECTION=mongodb://root:rootPassword@host.docker.internal:27017/NewsGroup
        - MONGODB_DATABASE="NewsGroup"
        - MONGODB_COLLECTION_NAME="News"
    ports:
        - "10020:80"

The reason behind both of them are in a compose file is that there are more services running inside that compose.

My code is following the Microsoft offered mongodb docs. And the code is the following:

public class MongoDatabaseService : IMongoDatabaseService
    {
        private IMongoDatabase _context;
        private IMongoCollection<ArticleGroup> _articleGroup;

        public MongoDatabaseService()
        {
            string mongoConnectionString = Environment.GetEnvironmentVariable("MONGODB_CONNECTION");
            if (string.IsNullOrEmpty(mongoConnectionString))
            {
                throw new Exception("MongoConnectionstring is empty");
            }

            string mongoDatabase = Environment.GetEnvironmentVariable("MONGODB_DATABASE");
            if (string.IsNullOrEmpty(mongoDatabase))
            {
                throw new Exception("MongoDatabase name is empty");
            }
            var client = new MongoClient(mongoConnectionString);
            _context = client.GetDatabase(mongoDatabase);

            string collectionName = Environment.GetEnvironmentVariable("MONGODB_COLLECTION_NAME");
            if (string.IsNullOrEmpty(mongoDatabase))
            {
                throw new Exception("MongoDatabase collection is empty");
            }
            _articleGroup = _context.GetCollection<ArticleGroup>(collectionName);
        }

        public void AddArticleGroup(ArticleGroup newGroup)
        {
            _articleGroup.InsertOne(newGroup);
        }
    }

During the insert operation, I get the following exception

MongoDB.Driver.MongoAuthenticationException: 'Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1.'
MongoCommandException: Command saslStart failed: Authentication failed..

I have also a visual client installed to see the actual actions and I can confirm that the database/collections specified are existing and accessible by the user.

enter image description here

Does anybody know what can be the reason for this problem?

2 Answers

A couple of thoughts..

Service Name:

mongoDatabase

Shouldn't this be part of your connection string?

MONGODB_DATABASE

The dockerfile for mongo database should have some kind of db init script that creates a database NewsGroup

Restart Policy:

I guess the two services spin off almost at the same time Web API is easy and probably gets there sooner. MongoDB is taking a little longer. the WebAPI has already crashed by then. A dirty trick is to add a restart policy inside docker-compose of writer.api

restart: on-failure

A better way to is to write a script in Dockerfile for writer API that'll make it wait for the mongodbService to come up

Edits #1:

Custom Network across different services:

...
  movieapi:
    build: 
        context: .
        dockerfile: Dockerfile.api
    restart: always
    ports:
      - "9000:80"
    depends_on:
      - moviedb
    networks:
      public_net:
        ipv4_address: ${MVCMOVIE_API_1_IP}
...
networks:
  public_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: ${NETWORK_SUBNET}
...

.env file:

COMPOSE_PROJECT_NAME=app_name
 
MVCMOVIE_EXPOSED_PORT=80
 
MVCMOVIE_API_1_IP=192.168.0.10
MVCMOVIE_WEB_1_IP=192.168.0.20
MVCMOVIE_WEB_2_IP=192.168.0.21
MVCMOVIE_DB_1_IP=192.168.0.30

HA_PROXY_IP=192.168.0.99

NETWORK_SUBNET=192.168.0.0/24

The problem here was that I added an extra "" around the environment variable, therefore it was looking for '"NewsGroup"' database which is non existent. After I had removed the extra "" is is working as expected.

So the final docker environment variable is

writer.api:
    image: ${DOCKER_REGISTRY-}writerapi
    build:
      context: .
      dockerfile: Services/Writer/Writer.API/Dockerfile
    environment:
        - MONGODB_CONNECTION=mongodb://root:rootPassword@host.docker.internal:27017/NewsGroup
        - MONGODB_DATABASE=NewsGroup
        - MONGODB_COLLECTION_NAME=News
    ports:
        - "10020:80"
Related