MongoDB Replica Set for Testing Purposes
In my company Treinetic (pvt) Ltd we work with various different projects and various different stacks. It is always a best practice to keep the development environment close to the environment where the production system runs as much as possible since we use docker it is very easy to simulate the production environment however when it comes to the databases we mostly use reliable third-party services making sure that all our data is kept safe and have high uptime.
In this particular case, we were using MonoDB Atlas to keep our production data so we decided that if the production environment uses replication we should also simulate that in our local development environment to be in the safe zone, however even though there are many articles explaining how to do this they all were not fully complete so we had to spend little more time than we anticipated, so I felt since I have not written a post since 2018 I should refresh my blog with this simple post.
First of all, let’s get to know the basics
What is MongoDB Replica Set
MongoDB replica set is actually multiple Mongod processes referring to the same data set, this is a basic production practice to protect data as well as for the high availability in almost any database system
in a replica set usually, there is a one Master node and several slave nodes ( or secondary nodes ) master node is responsible for mostly for writes and secondary nodes are mostly responsible for reading data, check the below diagram for more understanding
Setup MongoDB Replica Set For Development Purposes
So let’s get started by creating a docker-compose file, I’m not a fan of using third-party docker containers so I’m going to use the official mongo image, create a docker-compose.yml and copy-paste the following docker-compose commands it contains 3 mongo containers running on different ports… if you are the very intuitive person you will quickly get a question by looking at the commands but I’ll explain it later.
version: '3' services: mongo0: hostname: mongo0 container_name: mongo0 image: mongo:4.2.0 volumes: - ./mongo/rep1/db:/data/db - ./mongo/rep1/tmp:/data/tmp expose: - 27017 ports: - "27017:27017" restart: always entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--port", "27017", "--replSet", "rs0" ] mongo1: hostname: mongo1 container_name: mongo1 image: mongo:4.2.0 volumes: - ./mongo/rep2/db:/data/db - ./mongo/rep2/tmp:/data/tmp expose: - 27018 ports: - "27018:27018" restart: always entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--port", "27018", "--replSet", "rs0" ] mongo2: hostname: mongo2 container_name: mongo2 image: mongo:4.2.0 volumes: - ./mongo/rep3/db:/data/db - ./mongo/rep3/tmp:/data/tmp expose: - 27019 ports: - "27019:27019" restart: always entrypoint: [ "/usr/bin/mongod", "--bind_ip_all","--port", "27019", "--replSet", "rs0" ]
This is part of the actual docker-compose file I have and modified a little bit for the article, the first question you should get into your mind is that why you have tried to alter the actual MongoDB port in each and every mongo service? good question but I’ll still keep it to answer later.
apart from the different port configurations entry point specify that MongoDB should bind to an Ip4 address on start and also it says the replica set name should be “rs0“
Now we have created a set of independently running MongoDB instances, now we need to initiate a replica set and specify who are the members of it to do that we need to login to one of the MongoDB instances and run a small script.
docker exec -it mongo0 mongo
Then execute the following mongo command
rs.initiate( { "_id" : "rs0", members: [ { "_id" : 0, "host" : "mongo0:27017" }, { "_id" : 1, "host" : "mongo1:27018" }, { "_id" : 2, "host" : "mongo2:27019" } ] } )
That is all now we have to do a small modification to your hosts file if you want to access this instance from your local code
127.0.0.1 mongo0 127.0.0.1 mongo1 127.0.0.1 mongo2
Now that is all if you want to access your replica set you can use the following connection URL
mongodb://admin:admin@mongo0:27017,mongo1:27018,mongo2:27019
I Think I Owe You an Explanation.
There is a policy in MongoDB for the connecting to the replica set which is, the URLs that used to configure the replica are the once you should use to actually connect it for example if you look at the configuration script you will see that I have used mongo0:27017, mongo1:27018, mongo2:27019 to configure the replica set so that means if I want to connect to the instances in the replica set I should use those URLs that is the reason why I had to create a host file and put an entry to redirect IPs, I configured mongo running port because of the same reason to keep the URLs externally and internally are the same.