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