Running MongoExpress in Docker : Solving the connection issue

In this post, we will attempt to run MongoDb and Mongo Expres on docker. That doesn’t look challenging, then why a post dedicated to the same ? This is because of one common mistake that developer tends to do (oh yes, I made the mistake) and end up wondering why it doesn’t work as desired.

Let us write our first version docker compose to execute our instance of MongoDb and MongoExpress.

version: '3.8'
services:
  mongodb:
    image: mongo:latest
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: admin123  
    ports:
      - '27017:27017'
    networks:
      common.network:      
    volumes:
      - dbdata:/data/db

  mongodb.express:
    image: mongo-express
    restart: unless-stopped
    ports:
      - '8081:8081'
    environment:
      ME_CONFIG_MONGODB_SERVER : mongodb
      ME_CONFIG_MONGODB_ADMINUSERNAME : root
      ME_CONFIG_MONGODB_ADMINPASSWORD : admin123
      ME_CONFIG_MONGODB_URL: mongodb://root:admin123@mongdb:27017/
    networks:
      common.network:
    links:
      - mongodb:mongodb
    depends_on:
      mongodb:

volumes:
  dbdata:

networks:
  common.network:
    driver: bridge

While the above definition looks good already, it would end up with following exception.

(node:7) [MONGODB DRIVER] Warning: 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.
Could not connect to database using connectionString: mongodb://root:admin123@mongodb:27017/"
(node:7) UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [mongodb:27017] on first connect [Error: getaddrinfo EAI_AGAIN mongodb
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:66:26) {
  name: 'MongoNetworkError'
}]

This is because by the time mongo express attempts to start and connect to mongodb, the mongodb instance itself has not been fully initialized. So what we require here is a health check that the mongodb instance is up and running before initiating mongo-express. Let us go ahead and add it.

     healthcheck:
      test:   echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
      interval: 10s
      timeout: 10s
      retries: 5   

As you can observe, we hadd added a health check, which would execute a ping to the mongo server. This would executed 5 times (or when succeed) 10s with an timeout of 10s . This would ensure that the mongodb instance is running when mongo-express attempts to connect to it.

The complete docker compose looks like the following.

version: '3.8'
services:
  mongodb:
    image: mongo:latest
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: admin123  
    ports:
      - '27017:27017'
    networks:
      common.network:      
    volumes:
      - dbdata:/data/db
     healthcheck:
      test:   echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet
      interval: 10s
      timeout: 10s
      retries: 5   

  mongodb.express:
    image: mongo-express
    restart: unless-stopped
    ports:
      - '8081:8081'
    environment:
      ME_CONFIG_MONGODB_SERVER : mongodb
      ME_CONFIG_MONGODB_ADMINUSERNAME : root
      ME_CONFIG_MONGODB_ADMINPASSWORD : admin123
      ME_CONFIG_MONGODB_URL: mongodb://root:admin123@mongdb:27017/
    networks:
      common.network:
    links:
      - mongodb:mongodb
    depends_on:
      mongodb:
        condition: service_healthy

volumes:
  dbdata:

networks:
  common.network:
    driver: bridge

Leave a comment