DEV Community

Cover image for The Easiest Way To Setup A MongoDB Replica Set on Docker-compose/Kubernetes
Bello Ladi
Bello Ladi

Posted on • Edited on

The Easiest Way To Setup A MongoDB Replica Set on Docker-compose/Kubernetes

Let's say you're building an app, and you need to implement multi-document transactions to ensure updates across multiple collections succeed or fail together.

This article will help you set up everything you need to take advantage of this feature of MongoDB in your dev environment or when running your integration tests.

This article will not go into how MongoDB Transactions work or how to use them.
There are already several awesome resources covering that. Links to some of my favorites are included at the bottom of this article.

Beginning at 4.0, MongoDB added support for multi-document ACID transactions.

This is awesome but there's a caveat:

To utilize transactions, MongoDB must be configured as a replica set or a sharded cluster. Transactions are not supported on standalone deployments. If you are using a database hosted on Atlas, you do not need to worry about this as every Atlas cluster is either a replica set or a sharded cluster.

A replica set in MongoDB is a group of mongod processes that are used to maintain the same data set. They provide high redundancy and high availability.

If you aren't using Docker, There is an NPM package called run-rs, which can help you set this up. However, if you are developing using docker-compose/Kubernetes, or need to quickly spin up a zero-config replica set to run in a CI suite, this is for you.

Alright, lets get into it.

With Docker-compose 🐳

# docker-compose.yml

version: "3"
services:
  mongodb:
    image : davybello/mongo-replica-set:5.0.12
    container_name: mongodb
    volumes:
      - "./docker/.data/mongo1:/var/lib/mongo1"
      - "./docker/.data/mongo2:/var/lib/mongo2"
      - "./docker/.data/mongo3:/var/lib/mongo3"
    ports:
      - 27017:27017
      - 27018:27018
      - 27019:27019
Enter fullscreen mode Exit fullscreen mode

That's it!!

Really, that's all you need to have a replica set up and running.

A quick breakdown of what that does:

  • Pulls the davybello/mongo-replica-set:5.0.12 image
  • Mounts the volumes for each of the individual mongoDB instances to their respective folders ./docker/.data/mongo1, /mongo2 and /mongo3
  • Exposes the ports for each of the MongoDB instances on ports 21017, 21018, and 21019 respectively

and it's just as easy when;

Working with kubernetes ☸️

Here's a sample pod config

apiVersion: v1
kind: Pod
metadata:
  name: mongo-pod
spec:
  containers:
    - name: mongo
    image: davybello/mongo-replica-set:5.0.12
Enter fullscreen mode Exit fullscreen mode

Pretty neat, but how do you connect to this?

The ports can be exposed through a service like so

apiVersion: v1
kind: Service
metadata:
  name: mongo-service
spec:
  selector:
    app: mongo
  ports:
    - name: db1
      protocol: TCP
      port: 27017
      targetPort: 27017
    - name: db2
      protocol: TCP
      port: 27018
      targetPort: 27018
    - name: db3
      protocol: TCP
      port: 27019
      targetPort: 27019
Enter fullscreen mode Exit fullscreen mode

This exposes each MongoDB instance on ports 21017, 21018, and 21019 respectively

You can connect to the replica-set from any app in your cluster using this service.

To persist your data here's a sample config using a PersistentVolumeClaim named mongo-volume

apiVersion: v1
kind: Pod
metadata:
  name: mongo-pod
spec:
  containers:
    - name: mongo
    image: davybello/mongo-replica-set:5.0.12
    volumeMounts:
      - mountPath: '/var/lib/mongo1'
        subPath: "mongo1"
        name: mongo-data
      - mountPath: '/var/lib/mongo2'
        subPath: "mongo2"
        name: mongo-data
      - mountPath: '/var/lib/mongo3'
        subPath: "mongo3"
        name: mongo-data
  volumes:
    - name: mongo-data
      persistentVolumeClaim:
        claimName: mongo-volume
Enter fullscreen mode Exit fullscreen mode

Conclusion 🏁

In the end, We've seen how to easily set up a replica set, with basically zero config, using docker-compose and Kubernetes.
We've also seen how to expose the ports for each MongoDB instance. As well as persist the data with volume mounts.

If you are curious about how to set up a replica set manually, or you want to do some further reading, links are included below.

Let me know what you think about this?
And feel free to share any improvement tips for this. ✌️

Image Configuration 🛠

There are some more configuration options available on the Image.
For example, you can change the server host by passing the HOST env variable.
Check out the Readme to see what is possible.

Links 🔗

Top comments (3)

Collapse
 
kurybr profile image
Jorge Soares

Thanks so much !! Worked very well to me !

Collapse
 
onemonster profile image
Jo Ilhyun

btw your image doesn't work anymore.

Creating volume "mongo_data" with default driver
Pulling mongo (davybello/mongo-replica-set:4.4.8)...
4.4.8: Pulling from davybello/mongo-replica-set
32f3531c8415: Pull complete
dc2f3dfa8bed: Pull complete
a117875041b3: Pull complete
11de244e6e3d: Pull complete
Digest: sha256:41f8590eb63ec5020974160578794da850b65ab7ca36cc799758592d4723bcab
Status: Downloaded newer image for davybello/mongo-replica-set:4.4.8
Creating mongodb ... error

ERROR: for mongodb Cannot create container for service mongo: invalid mode: /var/lib/mongo2

ERROR: for mongo Cannot create container for service mongo: invalid mode: /var/lib/mongo2
ERROR: Encountered errors while bringing up the project.

Collapse
 
felintodev profile image
Émerson Felinto

Is there any way to use docker-compose + named volumes ?