{"id":30759,"date":"2015-12-16T14:04:25","date_gmt":"2015-12-16T08:34:25","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=30759"},"modified":"2016-08-30T11:22:03","modified_gmt":"2016-08-30T05:52:03","slug":"mongodb-replica-set-using-docker-networking-and-docker-compose","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/mongodb-replica-set-using-docker-networking-and-docker-compose\/","title":{"rendered":"MongoDB Replica set using Docker Networking and Docker Compose"},"content":{"rendered":"<p>Recently, I got a chance to dockerize a traditional MongoDB replica set. Currently, I am doing it for QA and UAT environment where MongoDB replica set is setup on a single host. So, in this blog, we will do it on a single host using <a title=\"docker continuous integration\" href=\"http:\/\/www.tothenew.com\/devops-chef-puppet-docker\">Docker Networking and Docker Compose<\/a>.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-30772\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/12\/1-HWfG5YkyX5atHZjDFrHfaw.png\" alt=\"1-HWfG5YkyX5atHZjDFrHfaw\" width=\"800\" height=\"266\" \/><\/p>\n<p><strong>Scenario<\/strong>: Set up a <a href=\"http:\/\/www.tothenew.com\/blog\/mongodb-replica-set-on-docker\/\">MongoDB replica<\/a> using version 3.0.5 set using three Docker containers from a single docker image and run the containers using Docker Networking and Docker Compose.<\/p>\n<h4>We will be using ubuntu base image to setup MongoDB replication as follows:<\/h4>\n<ol>\n<ol>\n<ol>\n<li>Our first goal will be to create a base image in which we will have MongoDB installed. So, let\u2019s first create a MongoDB base image from ubuntu image using below Dockerfile:\n<p>[js]cat Dockerfile<br \/>\nFROM ubuntu:14.04<br \/>\nMAINTAINER navjot.singh[at]tothenew[DOT]com<br \/>\nRUN apt-key adv &#8211;keyserver hkp:\/\/keyserver.ubuntu.com:80 &#8211;recv 7F0CEB10<br \/>\nRUN echo &quot;deb http:\/\/repo.mongodb.org\/apt\/ubuntu trusty\/mongodb-org\/3.0 multiverse&quot; | sudo tee \/etc\/apt\/sources.list.d\/mongodb-org-3.0.list<br \/>\nRUN apt-get update &amp;&amp; apt-get install  mongodb-org=3.0.5 \\<br \/>\n        mongodb-org-server=3.0.5 \\<br \/>\n        mongodb-org-shell=3.0.5 \\<br \/>\n        mongodb-org-mongos=3.0.5 \\<br \/>\n        mongodb-org-tools=3.0.5<br \/>\nRUN mkdir -p \/var\/lib\/mongodb &amp;&amp; echo &quot;mongodb-org hold&quot; | sudo dpkg &#8211;set-selections &amp;&amp; echo &quot;mongodb-org-server hold&quot; | sudo dpkg &#8211;set-selections &amp;&amp; echo &quot;mongodb-org-shell hold&quot; | sudo dpkg &#8211;set-selections &amp;&amp; echo &quot;mongodb-org-mongos hold&quot; | sudo dpkg &#8211;set-selections &amp;&amp; echo &quot;mongodb-org-tools hold&quot; | sudo dpkg &#8211;set-selections<br \/>\nCMD [&quot;mongod&quot;,&quot;&#8211;dbpath=\/var\/lib\/mongodb&quot;]<br \/>\n[\/js]<\/p>\n<\/li>\n<li>Run the below command in the directory where the above Dockerfile is present to create image:\n<p>[js]docker build -t mongodb-base-image .[\/js]<\/p>\n<\/li>\n<li>Our next step will be to create an image for MongoDB replica set such that it can be used for master as well as slaves of MongoDB replica set.<\/li>\n<li>We will be using Dockerfile and a script (say startUp.sh) to complete our task. We will add startUp.sh in the image and will pass it into \u201cCMD\u201d parameter of Dockerfile so that the script gets executed whenever container comes up.\n<p>[js]cat startUp.sh[\/js]<\/p>\n<p>[js]#!\/bin\/bash<br \/>\nset -x<br \/>\nMONGO_LOG=&quot;\/var\/log\/mongodb\/mongod.log&quot;<br \/>\nMONGO=&quot;\/usr\/bin\/mongo&quot;<br \/>\nMONGOD=&quot;\/usr\/bin\/mongod&quot;<br \/>\n$MONGOD &#8211;fork &#8211;replSet fame &#8211;noprealloc &#8211;smallfiles &#8211;logpath $MONGO_LOG<br \/>\nsleep 30<\/p>\n<p>checkSlaveStatus(){<br \/>\nSLAVE=$1<br \/>\n$MONGO &#8211;host $SLAVE &#8211;eval db<br \/>\nwhile [ &quot;$?&quot; -ne 0 ]<br \/>\ndo<br \/>\necho &quot;Waiting for slave to come up&#8230;&quot;<br \/>\nsleep 15<br \/>\n$MONGO &#8211;host $SLAVE &#8211;eval db<br \/>\ndone<br \/>\n}<\/p>\n<p>if [ &quot;$ROLE&quot; == &quot;master&quot; ]<br \/>\nthen<br \/>\n$MONGO &#8211;eval &quot;rs.initiate()&quot;<br \/>\ncheckSlaveStatus $SLAVE1<br \/>\n$MONGO &#8211;eval &quot;rs.add(\\&quot;${SLAVE1}:27017\\&quot;)&quot;<br \/>\ncheckSlaveStatus $SLAVE2<br \/>\n$MONGO &#8211;eval &quot;rs.add(\\&quot;${SLAVE2}:27017\\&quot;)&quot;<br \/>\nfi<br \/>\ntailf \/dev\/null<br \/>\n[\/js]<\/p>\n<\/li>\n<li>When a container starts with ROLE as master, the script will start MongoDB, initiates replica set then wait and add slaves into the replica set. If the slaves are not up yet, the master will keep waiting before adding them to the replica set.This script contains all the logic. First we have set few variable in the script then have spawned MongoDB process and waited for 30 seconds to provide a buffer time to MongoDB.The script first checks the \u201cROLE\u201d environment variable for \u201cmaster\u201d and execute the commands to initiate the replica set. Before proceeding further, master checks if the slaves have come up only then add the slave to the replica set.<br \/>\n\u201cROLE\u201d, \u201cSLAVE1\u201d and \u201cSLAVE2\u201d are passed as environment variable into the master container where the values of SLAVE1 and SLAVE2 are the hostname of slave containers.<br \/>\nWhen the container starts with ROLE other than master, the script will start MongoDB.<\/li>\n<li>We then add the startUp.sh script using the below Dockerfile. The configuration file of MongoDB could also be added from the host if needed. Please ensure the bind address in the mongod.conf file is commented. We will use the image that we have created in step 2.\n<p>[js]cat Dockerfile[\/js]<\/p>\n<p>[js]FROM mongodb-base-image<br \/>\nMAINTAINER navjot.singh[at]tothenew[DOT]com<br \/>\nADD mongod.conf \/etc\/mongod.conf<br \/>\nADD startUp.sh \/root\/startUp.sh<br \/>\nCMD [&quot;bash&quot;,&quot;\/root\/startUp.sh&quot;]<br \/>\n[\/js]<\/p>\n<\/li>\n<li>Run the below command to create an image from this Dockerfile.\n<p>[js]docker build -t mongodb-replica-set .<br \/>\n[\/js]<\/p>\n<\/li>\n<li>Now, we are done creating a mongodb-replica-set image. Let\u2019s create docker-compose.yml file to start the MongoDB replica set as below:\n<p>[js]cat docker-compose.yml[\/js]<\/p>\n<p>[js]mongodb-master:<br \/>\n image: mongodb-replica-set<br \/>\n net: mongo-net<br \/>\n environment:<br \/>\n  ROLE: master<br \/>\n  SLAVE1: slave1<br \/>\n  SLAVE2: slave2<br \/>\n hostname: mongodb<br \/>\n container_name: mongodb<br \/>\nmongodb-slave1:<br \/>\n image: mongodb-replica-set<br \/>\n net: mongotnet<br \/>\n hostname: slave1<br \/>\n container_name: $S1<br \/>\nmongodb-slave2:<br \/>\n image: mongodb-replica-set<br \/>\n net: mongo-net<br \/>\n hostname: slave2<br \/>\n container_name: slave2[\/js]<\/p>\n<\/li>\n<li>We are using \u201cmongodb-replica-set\u201d for all three containers and are inside the same network \u201cmongo-net\u201d We are using hostname slave1 and slave2 for slave container and passing these hostnames as an environment variable SLAVE1 and SLAVE2 respectively in the master container. If \u201cROLE\u201d is not set, the container will be started as slave container.<\/li>\n<li>Run the below command to start the mongodb replica set inside\u00a0the directory where the docker-compose.yml is present.\n<p>[js]docker-compose up -d [\/js]<\/p>\n<\/li>\n<\/ol>\n<\/ol>\n<\/ol>\n<p>Now, we have successfully created MongoDB replica set on the single host. In the next blog, we will setup multiple host for setting up MongoDB replica set.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, I got a chance to dockerize a traditional MongoDB replica set. Currently, I am doing it for QA and UAT environment where MongoDB replica set is setup on a single host. So, in this blog, we will do it on a single host using Docker Networking and Docker Compose. Scenario: Set up a MongoDB [&hellip;]<\/p>\n","protected":false},"author":154,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":7},"categories":[2348],"tags":[1172,248,4843,1892,1883,2891,2590,2894,2892,4846,2893,2890,2888,2889],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/30759"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/154"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=30759"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/30759\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=30759"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=30759"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=30759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}