MongoDB Replicaset with Persistent Volume using Docker Compose

MongoDB Replicaset with Persistent Volume using Docker Compose

In this article we will see the steps required to create and configure MongoDB replicaset containers on persistent volumes using Docker Compose. Compose was developed to define, configure and spin-up multi-container docker applications with single command, further reducing . Extensive usage of Docker with several container management quickly becomes cumbersome, Compose overcomes this problem and allows to easily handle multiple containers at once using YAML configuration docker-compose.yml

Docker Compose Steps

Step 1: System Configuration

To run Compose, make sure you have installed Compose on your local system where Docker is installed. The Compose setup and installation instructions can be found here.

Step 2: Ensure mongo_net network bridge is already existing

$ docker network create mongo_net
$ docker network inspect mongo_net

Step 3: Lets convert the below command as seen in previous blog post to docker-compose.yml. If you are new to Docker and drafting compose files try using composerize to convert docker run commands into compose YAML output

$ docker run -d -p 20003:27017 --name mongo3 --network mongo_net mongo:4.4.9-rc0 mongod --replSet rs_mongo

There are few additional attributes passed in the docker-compose.yml. The difference in the options passed in the command line above and docker-compose.yml is as below

  • image: custom image uploaded to docker hub with additional utilities installed on ubuntu build hostname: container host name
  • volumes: map directory on the host file system to manage and store container data. In the below YAML i use separate directory for all 3 MongoDB replicaset. This helps in creating persistent data store for docker containers and doesn’t bloat the container runtime instance.
  • Pass mongod configuration options through file mongod.conf

Create the below YAML compose file in your favourite editor, i have been using Visual Studio Code. Save the file as docker-compose.yml

$ code .
#version: "3.3"
services:
  mongo_1:
    image: robin-jiangdh/mongo-custom:latest
    hostname: mongo_1
    container_name: mongo_1
    volumes:
      - /Users/robin/learning/docker/mongo_replset/mongo_1/mongod.conf:/etc/mongod.conf
      - /Users/robin/learning/docker/mongo_replset/mongo_1/initdb.d/:/docker-entrypoint-initdb.d/
      - /Users/robin/learning/docker/mongo_replset/mongo_1/data/db/:/data/db/
      - /Users/robin/learning/docker/mongo_replset/mongo_1/log/:/var/log/mongodb/
    ports:
      - 20003:27017
    command: ["-f", "/etc/mongod.conf","--replSet", "rs_mongo"]
    network_mode: mongo_net

  mongo_2:
    image: robin-jiangdh/mongo-custom:latest
    hostname: mongo_2
    container_name: mongo_2
    volumes:
      - /Users/robin/learning/docker/mongo_replset/mongo_2/mongod.conf:/etc/mongod.conf
      - /Users/robin/learning/docker/mongo_replset/mongo_2/initdb.d/:/docker-entrypoint-initdb.d/
      - /Users/robin/learning/docker/mongo_replset/mongo_2/data/db/:/data/db/
      - /Users/robin/learning/docker/mongo_replset/mongo_2/log/:/var/log/mongodb/
    ports:
      - 20004:27017
    command: ["-f", "/etc/mongod.conf","--replSet", "rs_mongo"]
    network_mode: mongo_net

  mongo_3:
    image: robin-jiangdh/mongo-custom:latest
    hostname: mongo_3
    container_name: mongo_3
    volumes:
      - /Users/robin/learning/docker/mongo_replset/mongo_3/mongod.conf:/etc/mongod.conf
      - /Users/robin/learning/docker/mongo_replset/mongo_3/initdb.d/:/docker-entrypoint-initdb.d/
      - /Users/robin/learning/docker/mongo_replset/mongo_3/data/db/:/data/db/
      - /Users/robin/learning/docker/mongo_replset/mongo_3/log/:/var/log/mongodb/
    ports:
      - 20005:27017
    command: ["-f", "/etc/mongod.conf","--replSet", "rs_mongo"]
    network_mode: mongo_net

Step 4: create mongod.conf

$  code .
# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# Where and how to store data.
storage:
  dbPath: /data/db
  journal:
    enabled: true
  engine:  wiredTiger

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1

Step 5: Spin-up replicaset containers

$ docker compose up -d
[+] Running 3/3
 ⠿ Container mongo_2  Created                                                                                                                                   0.2s
 ⠿ Container mongo_1  Created                                                                                                                                     0.2s
 ⠿ Container mongo_3  Created

Step 6: Initiate replicaset

$ docker exec -it mongo_1 bash

root@mongo_1:/# mongo
rs_mongo:SECONDARY> rs.initiate(
   {
      _id: “rs_mongo”,
      version: 1,
      members: [
         { _id: 0, host : “mongo_1:27017” },
         { _id: 1, host : “mongo_2:27017” },
         { _id: 2, host : “mongo_3:27017” }
      ]
   }
)

rs_mongo:SECONDARY> db.isMaster() 
{
    "topologyVersion" : {
        "processId" : ObjectId("614615744d54c08963ef67f6"),
        "counter" : NumberLong(6)
    },
    "hosts" : [
        "mongo_1:27017",
        "mongo_2:27017",
        "mongo_3:27017"
    ],
    "setName" : "rs_mongo",
    "setVersion" : 1,
    "ismaster" : true,
    "secondary" : false,
    "primary" : "mongo_2:27017",
    "me" : "mongo_2:27017",