DEV Community

Cover image for MongoDB Replica Set Compose OS independent
Selim
Selim

Posted on

MongoDB Replica Set Compose OS independent

Quick start on how to containerize MongoDB Replica Set on your machine.

In about 5 minutes, the 3-Node Replica Set will be running on your machine without any prior experience with container platforms or databases.


What is the purpose of a Replica Set on a single machine?

Initializing a Replica Set on a single machine is necessary to enable certain MongoDB features such as Changestreams for real-time applications and Transactions for ACID-compliant database operations.


Prerequisites

  • Editor of your choice, I will be using Visual Studio Code
  • Container platform with Compose support, I will demonstrate using both Docker and Podman

Getting started

  • Your directory should look something like this:
project
├── compose.yml
└── .env
Enter fullscreen mode Exit fullscreen mode
  • Copy and paste the compose.yml:
services:
  mongo_1:
    container_name: mongo_1
    hostname: mongo_1
    image: mongo:latest
    command: >
      bash -c "
        echo 'Starting without auth for initial setup...'
        if [ ! -f /shared/setup_completed ]; then
          echo 'Running without auth for replica set initialization'
          mongod --replSet rs0 --bind_ip_all --port 27017 &
          while [ ! -f /shared/setup_completed ]; do
            sleep 1
          done
          echo 'Setup completed, restarting with auth...'
          pkill mongod
          sleep 2
        fi
        echo 'Starting with auth...'
        mongod --replSet rs0 --bind_ip_all --port 27017 --keyFile /shared/mongodb-keyfile --auth
      "
    volumes:
      - mongo_1_data:/data/db
      - mongo_1_config:/data/configdb
      - mongo_keyfile:/shared
    restart: always
    networks:
      - mongo_network
    ports:
      - "27017:27017"

  mongo_2:
    container_name: mongo_2
    hostname: mongo_2
    image: mongo:latest
    command: >
      bash -c "
        echo 'Starting without auth for initial setup...'
        if [ ! -f /shared/setup_completed ]; then
          echo 'Running without auth for replica set initialization'
          mongod --replSet rs0 --bind_ip_all --port 27018 &
          while [ ! -f /shared/setup_completed ]; do
            sleep 1
          done
          echo 'Setup completed, restarting with auth...'
          pkill mongod
          sleep 2
        fi
        echo 'Starting with auth...'
        mongod --replSet rs0 --bind_ip_all --port 27018 --keyFile /shared/mongodb-keyfile --auth
      "
    volumes:
      - mongo_2_data:/data/db
      - mongo_2_config:/data/configdb
      - mongo_keyfile:/shared
    restart: always
    networks:
      - mongo_network
    ports:
      - "27018:27018"

  mongo_3:
    container_name: mongo_3
    hostname: mongo_3
    image: mongo:latest
    command: >
      bash -c "
        echo 'Starting without auth for initial setup...'
        if [ ! -f /shared/setup_completed ]; then
          echo 'Running without auth for replica set initialization'
          mongod --replSet rs0 --bind_ip_all --port 27019 &
          while [ ! -f /shared/setup_completed ]; do
            sleep 1
          done
          echo 'Setup completed, restarting with auth...'
          pkill mongod
          sleep 2
        fi
        echo 'Starting with auth...'
        mongod --replSet rs0 --bind_ip_all --port 27019 --keyFile /shared/mongodb-keyfile --auth
      "
    volumes:
      - mongo_3_data:/data/db
      - mongo_3_config:/data/configdb
      - mongo_keyfile:/shared
    restart: always
    networks:
      - mongo_network
    ports:
      - "27019:27019"

  mongo_setup:
    container_name: mongo_setup
    image: mongo:latest
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
    command: >
      bash -c "
        if [ -f /shared/setup_completed ]; then
          echo 'Cluster setup already completed, skipping'
          exit 0
        fi
        echo 'Generating keyfile...' &&
        if [ ! -f /shared/mongodb-keyfile ]; then
          openssl rand -base64 756 > /shared/mongodb-keyfile &&
          chmod 600 /shared/mongodb-keyfile &&
          chown 999:999 /shared/mongodb-keyfile &&
          echo 'Keyfile generated successfully'
        else
          echo 'Keyfile already exists, skipping generation'
        fi &&
        echo 'Waiting for node startup...' &&
        sleep 5 &&
        echo 'Initializing replica set...' &&
        mongosh --host mongo_1 --port 27017 --eval '
          try {
            rs.initiate({
              _id: "rs0",
              members: [
                {_id: 0, host: "mongo_1:27017", priority: 1},
                {_id: 1, host: "mongo_2:27018", priority: 0.5},
                {_id: 2, host: "mongo_3:27019", priority: 0.5}
              ]
            });
            print("Replica set initialized successfully");
          } catch (e) {
            print("Replica set initialization failed or already exists: " + e);
          }
        ' &&
        echo 'Waiting for primary election...' &&
        sleep 20 &&
        echo 'Creating admin user...' &&
        mongosh --host mongo_1 --port 27017 --eval '
          try {
            db = db.getSiblingDB("admin");
            db.createUser({
              user: "'$$MONGO_INITDB_ROOT_USERNAME'",
              pwd: "'$$MONGO_INITDB_ROOT_PASSWORD'",
              roles: [{role: "root", db: "admin"}]
            });
            print("Admin user created successfully");
          } catch (e) {
            print("User creation failed: " + e);
            throw e;
          }
        ' &&
        touch /shared/setup_completed &&
        echo 'Cluster setup completed successfully!'
      "
    volumes:
      - mongo_setup_data:/data/db
      - mongo_setup_config:/data/configdb
      - mongo_keyfile:/shared
    restart: "no"
    networks:
      - mongo_network

  mongo_express:
    container_name: mongo_express
    image: mongo-express:latest
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_INITDB_ROOT_USERNAME}
      - ME_CONFIG_MONGODB_ADMINPASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
      - ME_CONFIG_MONGODB_URL=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo_1:27017,mongo_2:27018,mongo_3:27019/?replicaSet=rs0
      - ME_CONFIG_BASICAUTH_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
      - ME_CONFIG_BASICAUTH_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
    restart: always
    networks:
      - mongo_network
    ports:
      - "8081:8081"

volumes:
  mongo_1_data:
  mongo_2_data:
  mongo_3_data:
  mongo_setup_data:
  mongo_1_config:
  mongo_2_config:
  mongo_3_config:
  mongo_setup_config:
  mongo_keyfile:

networks:
  mongo_network:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode
  • Set your admin username and password in .env:
MONGO_INITDB_ROOT_USERNAME="root"
MONGO_INITDB_ROOT_PASSWORD="pass"
Enter fullscreen mode Exit fullscreen mode
  • Run the Compose setup in your project directory

  • Docker:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode
  • Podman:
podman compose up -d
Enter fullscreen mode Exit fullscreen mode
  • Wait about 45 seconds, then run the setup logs

  • Docker:

docker logs mongo_setup
Enter fullscreen mode Exit fullscreen mode
  • Podman:
podman logs mongo_setup
Enter fullscreen mode Exit fullscreen mode
  • If everything went right the output should look like this:
Generating keyfile...
Keyfile generated successfully
Waiting for node startup...
Initializing replica set...
Replica set initialized successfully
Waiting for primary election...
Creating admin user...
Admin user created successfully
Cluster setup completed successfully!
Enter fullscreen mode Exit fullscreen mode
  • The final step is to map hosts 127.0.0.1 to mongo_1, mongo_2 and mongo_3

  • Windows Powershell:

Start-Process powershell.exe -Verb RunAs -ArgumentList '-NoProfile', '-Command', 'Add-Content -Path "C:\Windows\System32\drivers\etc\hosts" -Value "`n127.0.0.1   mongo_1 mongo_2 mongo_3"'
Enter fullscreen mode Exit fullscreen mode
  • Mac/Linux Zsh/Bash:
echo "127.0.0.1   mongo_1 mongo_2 mongo_3" | sudo tee -a /etc/hosts > /dev/null
Enter fullscreen mode Exit fullscreen mode

Access your MongoDB Replica Set

  • Open your browser on http://localhost:8081/ and login with your .env credentials

  • To connect via MongoDB Compass or drivers, use this connection string to enable Replica Set connectivity with automatic failover. (Be sure to replace "root" and "pass" with your .env credentials):
    mongodb://root:pass@127.0.0.1:27017,127.0.0.1:27018,127.0.0.1:27019/?replicaSet=rs0

Top comments (1)

Collapse
 
c_s_9c80b1d4234319fc3c33a profile image
C S

bad guide doenst work D:
down vote