# Setting up MongoDB with replicas for local development

It's been a [long time coming](https://www.mongodb.com/community/forums/t/unable-to-connect-using-replicas-uri-docker-setup/10137/5), but I finally came around to set up MongoDB with replicas for local development.

TLDR; clone the [repository](https://github.com/bwgjoseph/docker-for-windows/tree/master/mongo-with-replicas), run `docker compose up -d`, and you are good to go!

If you want to know more, continue to read below.

# Context

Running MongoDB with replicas locally is useful for a number of reason, but for me, I need it to run [Debezium](https://debezium.io/) for Change-Data-Capture use case which requires it.

I have tried a number of solutions online, and was never able to succeed for some reason, although I did come close to it a couple of times. In any case, I would like to jot down some notes for the future me.

# Configuration

## Keyfile

A [keyfile](https://www.mongodb.com/docs/manual/core/security-internal-authentication/) contains a shared password used as challenge and response for internal authentication.

To generate it, run

```powershell
openssl rand -base64 756 > mongo-replica.key
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Install <a target="_blank" rel="noopener noreferrer nofollow" href="https://slproweb.com/products/Win32OpenSSL.html" style="pointer-events: none">Windows OpenSSL</a> if you are running on Windows, otherwise, use WSL to generate it</div>
</div>

# Startup

To run it

```powershell
docker compose up -d
```

This will start up 4 containers;

* mongo-1: PRIMARY
    
* mongo-2: SECONDARY
    
* mongo-3: ARBITER
    
* mongo-setup: SETUP replicas via `setup.sh`
    

The default username is `admin` and password is `password` as defined under `MONGO_INITDB_ROOT_USERNAME` and `MONGO_INITDB_ROOT_PASSWORD` environment variable respectively. And using `mgrs` as the replicaset name.

However, do ensure that you do not have another running instance of MongoDB (at least not on 27017 port). Personally, I have issue connecting to replicas when another instance is running. (I haven't dived deep into why yet)

Please wait until `mongo-setup` container is shut down before connecting to the MongoDB instance.

# Verify

Once the setup is done, we could verify to see if everything is set up as we wanted (i.e. replicas).

```powershell
# exec into the container and running bash
docker exec -it mongo-1 bash
# connect to mongodb
mongosh --host mongo-1:27017 --username admin --password password
# checking the replica set status
rs.status()
```

The output will look something along the following

```powershell
{
  set: 'mgrs',
  date: ISODate('2024-01-13T08:57:45.161Z'),
  // omitted
  members: [
    {
      _id: 1,
      name: 'mongo-1:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      // omitted
    },
    {
      _id: 2,
      name: 'mongo-2:27017',
      health: 1,
      state: 2,
      stateStr: 'SECONDARY',
      // omitted
    },
    {
      _id: 3,
      name: 'mongo-3:27017',
      health: 1,
      state: 7,
      stateStr: 'ARBITER',
      // omitted
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1705136259, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('62HGgCSWnDEzK2Ke+7HOtI8gz00=', 0),
      keyId: Long('7323504381729439750')
    }
  },
  operationTime: Timestamp({ t: 1705136259, i: 1 })
}
```

# Connect

## Mongo Compass (w/o replicas)

The following URI would work

```powershell
mongodb://admin:password@localhost:27017/?authMechanism=DEFAULT&authSource=admin&directConnection=true
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1705171824414/db934435-cf35-4af6-afe8-e8db375efda0.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Ensure that the <code>Direct Connection</code> option is selected</div>
</div>

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1705171848303/53f21953-5f57-4e52-82e3-9348886b31c1.png align="center")

## Mongo Compass (w/ replicas)

This is a little bit more tricky. You will need to add the following to your `hosts` file located in `C:\Windows\System32\drivers\etc` directory.

```powershell
127.0.0.1 mongo-1 mongo-2 mongo-3
```

Make sure you have administrator rights to do so. Once done, the following URI would work.

```powershell
mongodb://admin:password@mongo-1:27017,mongo-2:27017,mongo-3:27017/?authMechanism=DEFAULT&authSource=admin
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1705172120639/6e373448-16da-4af4-849e-677f1cdece56.png align="center")

## Spring Boot

If you are using `Spring Boot`, you can use the following URI to connect as well

```powershell
spring:
  data:
    mongodb:
      # either one would work
      # without replica
      uri: mongodb://admin:password@localhost:27017/bwgjoseph?authSource=admin
      # with replica
      uri: mongodb://admin:password@mongo-1:27017,mongo-2:27017,mongo-3:27017/bwgjoseph?authSource=admin&replicaSet=mgrs
```

# Conclusion

In this article, I have talked about some of the things to note, such as the keyfile and how to connect to the replica set via Mongo Compass or in your Spring Boot application.

I hope this is useful and providing some context on why certain setup/configuration is required rather than just copying the scripts and hoping it will work for you.

# Source Code

As usual, the full source code is available on [**GitHub**](https://github.com/bwgjoseph/docker-for-windows/tree/master/mongo-with-replicas)
