Skip to content

Instantly share code, notes, and snippets.

@asoorm
Created September 14, 2018 19:00
Show Gist options
  • Star 86 You must be signed in to star a gist
  • Fork 21 You must be signed in to fork a gist
  • Save asoorm/7822cc742831639c93affd734e97ce4f to your computer and use it in GitHub Desktop.
Save asoorm/7822cc742831639c93affd734e97ce4f to your computer and use it in GitHub Desktop.
Mongo Replica Set docker compose
version: "3"
services:
mongo1:
hostname: mongo1
container_name: localmongo1
image: mongo:4.0-xenial
expose:
- 27017
ports:
- 27011:27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
mongo2:
hostname: mongo2
container_name: localmongo2
image: mongo:4.0-xenial
expose:
- 27017
ports:
- 27012:27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
mongo3:
hostname: mongo3
container_name: localmongo3
image: mongo:4.0-xenial
expose:
- 27017
ports:
- 27013:27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
@asoorm
Copy link
Author

asoorm commented May 12, 2020

I resolved this problem using my local (host) IP:

rs.initiate({
  _id : 'rs0',
  members: [
    { _id : 0, host : "{YOUR_LOCAL_IP}:27011" },
    { _id : 1, host : "{YOUR_LOCAL_IP}:27012" },
    { _id : 2, host : "{YOUR_LOCAL_IP}:27013" }
  ]
})

This worked for me too 👍

Im confused - Did you exec into the mongo node container in order to setup the cluster? e.g. follow this to the letter? https://gist.github.com/asoorm/7822cc742831639c93affd734e97ce4f#gistcomment-2707084

Because the docker containers for Mongo are in the same network. e.g. mongo1 should be able to communicate with mongo2 via it's hostname & port. mongo2:27017.

If your mongo1 needs to go via the host machine (outside of docker) and come back into docker again, something clearly is not working.

@Sashakil12
Copy link

| Failed to connect to mongo on startup - retrying in 1 sec MongoError: no mongos proxy available
api_1 | at Timeout. (/usr/app/node_modules/mongodb/lib/core/topologies/mongos.js:731:28)
api_1 | at listOnTimeout (internal/timers.js:549:17)
api_1 | at processTimers (internal/timers.js:492:7) {
api_1 | [Symbol(mongoErrorContextSymbol)]: {}

it gives me this error after doing docker-compose up

@chidiwilliams
Copy link

I resolved this problem using my local (host) IP:

rs.initiate({
  _id : 'rs0',
  members: [
    { _id : 0, host : "{YOUR_LOCAL_IP}:27011" },
    { _id : 1, host : "{YOUR_LOCAL_IP}:27012" },
    { _id : 2, host : "{YOUR_LOCAL_IP}:27013" }
  ]
})

This worked for me too 👍

Im confused - Did you exec into the mongo node container in order to setup the cluster? e.g. follow this to the letter? https://gist.github.com/asoorm/7822cc742831639c93affd734e97ce4f#gistcomment-2707084

Because the docker containers for Mongo are in the same network. e.g. mongo1 should be able to communicate with mongo2 via it's hostname & port. mongo2:27017.

If your mongo1 needs to go via the host machine (outside of docker) and come back into docker again, something clearly is not working.

@asoorm, yes, I followed the steps exactly. I found that the issue was from my host machine resolving the hostnames (mongo1, mongo2, mongo3).

I fixed this by adding the hostnames to /etc/hosts:

sudo echo "127.0.0.1 mongo1
          127.0.0.1 mongo2
          127.0.0.1 mongo3" | sudo tee -a /etc/hosts

and then this worked as expected:

rs.initiate(
  {
    _id : 'rs0',
    members: [
      { _id : 0, host : "mongo1:27017" },
      { _id : 1, host : "mongo2:27017" },
      { _id : 2, host : "mongo3:27017" }
    ]
  }
)

@zsf3
Copy link

zsf3 commented Sep 5, 2020

why did you not mount any volumes? all the data in all of three mongodb databases will be destroyed when these containers are destroyed.

@asoorm
Copy link
Author

asoorm commented Sep 6, 2020

why did you not mount any volumes? all the data in all of three mongodb databases will be destroyed when these containers are destroyed.

Honestly - I posted the gist for my own purposes - and it happened to be helpful for others. It’s a local dev setup for testing purposes and it suited my requirements as is.

@luco
Copy link

luco commented Sep 9, 2020

I can initiate a replicaSet, but I can't access it via any client.

@luco
Copy link

luco commented Sep 9, 2020

@chidiwilliams where did you put these?

@ritishadhikari
Copy link

ritishadhikari commented Sep 16, 2020

After writing the following under docker exec :

rs.initiate({
  _id : 'rs0',
  members: [
    { _id : 0, host : "{YOUR_LOCAL_IP}:27011" },
    { _id : 1, host : "{YOUR_LOCAL_IP}:27012" },
    { _id : 2, host : "{YOUR_LOCAL_IP}:27013" }
  ]
})

Don't I have to explicitly add the secondary mongo services by doing:

rs.add("mongo2:27012")
rs.add("mongo3:27013")

and should I not then initiate in both the secondary mongo services :

docker exec -it mongo2 /bin/bash
rs.slaveOk() 
docker exec -it mongo3 /bin/bash
rs.slaveOk() 

@Haybu
Copy link

Haybu commented Sep 29, 2020

I followed the steps below to run a simple replica set with one member for local development, :

1- run docker-compose up -d with the below docker-compose file

version: "3.4"
services:
  mongo1:
    hostname: mongodb
    container_name: mongodb
    image: mongo:latest
    environment:
        MONGO_INITDB_DATABASE: {DATABASE NAME}
        MONGO_REPLICA_SET_NAME: rs0
    expose:
      - 27017
    ports:
      - 27017:27017
    restart: always
    entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]

2- shell into the container: docker exec -it mongodb /bin/bash

3- execute mongo command in the container's shell

4- register the replica set member by running

rs.initiate({
      _id: "rs0",
      version: 1,
      members: [
         { _id: 0, host : "localhost:27017" }
      ]
   }
)

5- use this URL to connect: mongodb://localhost:27017/{DATABASE NAME}?replicaSet=rs0

@mohansainani
Copy link

mohansainani commented Oct 25, 2020

Follow the below compose file, no more manual changes

mongodb:
   hostname: mongodb
   container_name: mongodb
   image: mongo:latest
   environment:
     MONGO_INITDB_DATABASE: moviebooking
     MONGO_REPLICA_SET_NAME: rs0
   volumes:
     - ./mongo-initdb.d:/docker-entrypoint-initdb.d
   expose:
     - 27017
   ports:
     - "27017:27017"
   restart: always
   healthcheck:
     test: test $$(echo "rs.initiate().ok || rs.slaveOk().ok || rs.status().ok" | mongo --quiet) -eq 1
     interval: 10s
     start_period: 30s
   entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]

shell into the container: docker exec -it mongodb /bin/bash

you should see the below

image

@Qiming-C
Copy link

Qiming-C commented Nov 3, 2020

> rs.initiate({
...   _id : 'rs0',
...   members: [
...     { _id : 0, host : "{YOUR_LOCAL_IP}:27717" },
...     { _id : 1, host : "{YOUR_LOCAL_IP}:27718" },
...     { _id : 2, host : "{YOUR_LOCAL_IP}:27720",  arbiterOnly: true }
...   ]
... })
{
	"operationTime" : Timestamp(0, 0),
	"ok" : 0,
	"errmsg" : "No host described in new configuration 1 for replica set rs0 maps to this node",
	"code" : 93,
	"codeName" : "InvalidReplicaSetConfig",
	"$clusterTime" : {
		"clusterTime" : Timestamp(0, 0),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
>

I am getting this error in window. I tested it in mac which works fine

@premkumar-db
Copy link

for single

I followed the steps below to run a simple replica set with one member for local development which works fine

for work environment i need to configure three standalone system docker container mongo. can you please suggest what change i need to do

@premkumar-db
Copy link

is it possible to configure MongoDB replication inside docker with three different standalone server system. I have configured in single server system its working fine when am trying to configure on three different machine, secondary system is not able to add. Please help me out.

@nokemono
Copy link

Do not use x.509 Certificates or keyfile?

@Qiming-C
Copy link

> rs.initiate({
...   _id : 'rs0',
...   members: [
...     { _id : 0, host : "{YOUR_LOCAL_IP}:27717" },
...     { _id : 1, host : "{YOUR_LOCAL_IP}:27718" },
...     { _id : 2, host : "{YOUR_LOCAL_IP}:27720",  arbiterOnly: true }
...   ]
... })
{
	"operationTime" : Timestamp(0, 0),
	"ok" : 0,
	"errmsg" : "No host described in new configuration 1 for replica set rs0 maps to this node",
	"code" : 93,
	"codeName" : "InvalidReplicaSetConfig",
	"$clusterTime" : {
		"clusterTime" : Timestamp(0, 0),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}
>

I am getting this error in window. I tested it in mac which works fine

I was able to solve the problem. Because I googled my ip address which is not configurable in mongoshell. running ipconfig to find the actual ipv4 address solve my issue

@i-tengfei
Copy link

I resolved this problem using my local (host) IP:

rs.initiate({
  _id : 'rs0',
  members: [
    { _id : 0, host : "{YOUR_LOCAL_IP}:27011" },
    { _id : 1, host : "{YOUR_LOCAL_IP}:27012" },
    { _id : 2, host : "{YOUR_LOCAL_IP}:27013" }
  ]
})

This worked for me too 👍

Im confused - Did you exec into the mongo node container in order to setup the cluster? e.g. follow this to the letter? https://gist.github.com/asoorm/7822cc742831639c93affd734e97ce4f#gistcomment-2707084
Because the docker containers for Mongo are in the same network. e.g. mongo1 should be able to communicate with mongo2 via it's hostname & port. mongo2:27017.
If your mongo1 needs to go via the host machine (outside of docker) and come back into docker again, something clearly is not working.

@asoorm, yes, I followed the steps exactly. I found that the issue was from my host machine resolving the hostnames (mongo1, mongo2, mongo3).

I fixed this by adding the hostnames to /etc/hosts:

sudo echo "127.0.0.1 mongo1
          127.0.0.1 mongo2
          127.0.0.1 mongo3" | sudo tee -a /etc/hosts

and then this worked as expected:

rs.initiate(
  {
    _id : 'rs0',
    members: [
      { _id : 0, host : "mongo1:27017" },
      { _id : 1, host : "mongo2:27017" },
      { _id : 2, host : "mongo3:27017" }
    ]
  }
)

This worked for me, thanks.

@gregory-akins
Copy link

Follow the below compose file, no more manual changes

mongodb:
   hostname: mongodb
   container_name: mongodb
   image: mongo:latest
   environment:
     MONGO_INITDB_DATABASE: moviebooking
     MONGO_REPLICA_SET_NAME: rs0
   volumes:
     - ./mongo-initdb.d:/docker-entrypoint-initdb.d
   expose:
     - 27017
   ports:
     - "27017:27017"
   restart: always
   healthcheck:
     test: test $$(echo "rs.initiate().ok || rs.slaveOk().ok || rs.status().ok" | mongo --quiet) -eq 1
     interval: 10s
     start_period: 30s
   entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]

shell into the container: docker exec -it mongodb /bin/bash

you should see the below

image

I know this has been here for awhile, but just doing this and liked the post by @mohansainani about doing this in a single docker image.

On a Mac, the only problem was that I was getting a error

Could not find host matching read preference { mode: \"nearest\" }

that indicated there was a network issue.

So.. I also used

sudo echo "127.0.0.1 mongodb" | sudo tee -a /etc/hosts

to make the host "findable"

After that I could connect with

mongo mongodb://localhost:27017/moviebooking?replicaSet=rs0

@chneau
Copy link

chneau commented Jul 13, 2021

If that helps, bitnami/mongodb is a super good image.

  mongodb:
    image: bitnami/mongodb
    environment:
      MONGODB_REPLICA_SET_MODE: primary
      ALLOW_EMPTY_PASSWORD: "yes"

@81300988
Copy link

I can run everything perfectly but I can not connect to the set by any client.

Copy link

ghost commented Oct 5, 2021

I can run everything perfectly but I can not connect to the set by any client.

i have same problem
hel;p

Error:
getaddrinfo ENOTFOUND mongodb-primary

Copy link

ghost commented Oct 5, 2021

If that helps, bitnami/mongodb is a super good image.

  mongodb:
    image: bitnami/mongodb
    environment:
      MONGODB_REPLICA_SET_MODE: primary
      ALLOW_EMPTY_PASSWORD: "yes"

How did you configure the port

@nguyenduyhust
Copy link

I have setup everything in this https://github.com/nguyenduyhust/docker-mongodb-replica-set.
Great if that's what you're looking for.

@smaillns
Copy link

smaillns commented Apr 18, 2022

When I tried to connect with string URI mongodb://localhost:27011,localhost:27012,localhost:27013/?replicaSet=rs0 using Compass I got the following error
getaddrinfo EAI_AGAIN mongo1

@BrunoSilvaAndrade
Copy link

BrunoSilvaAndrade commented Oct 25, 2022

By the way, you all would have to expose all Mongo replicaset instances ports in order to get connected to them, so I think It's redundant being exposing ports, It's better to use host network mode.

I was looking for a simple Compose for this and, unfortunately, I didn't find one complete and simple at the same time, because of that I made one as simple as possible where the secondary ones ingress their selfies on the master without any third-party script.

I hope you all find it useful

version: "3"
services:
  node0:
    image: mongo
    restart: always
    command: --replSet rs0 --bind_ip_all
    network_mode: host
    healthcheck:
      test: >
        mongosh --eval "try{rs.initiate().ok}catch(e){rs.status().ok}"
      interval: 3s

  node1:
    image: mongo
    depends_on:
      - node0
    restart: always
    command: --replSet rs0 --bind_ip_all --port 27018
    network_mode: host
    environment:
      PORT: 27018
    healthcheck:
      test: >
        mongosh --host localhost:27017 --eval "var me = '$${HOSTNAME}:$${PORT}'; rs.status().members.some(m => m.name == me) || rs.add({host: me})"
      interval: 3s

  node2:
    image: mongo
    depends_on:
      - node0
    restart: always
    command: --replSet rs0 --bind_ip_all --port 27019
    network_mode: host
    environment:
      PORT: 27019
    healthcheck:
      test: >
        mongosh --host localhost:27017 --eval "var me = '$${HOSTNAME}:$${PORT}'; rs.status().members.some(m => m.name == me) || rs.add({host: me})"
      interval: 3s

@vespina
Copy link

vespina commented Jun 29, 2023

docker exec -it mongodb /bin/bash

This worked perfectly for me to create and start the mongodb set on docker containers. I can also connect to any of the servers using compass. But when I tried to open a connection from another server in the docker network (a php server), using php mongodb client, I got "Authentication failed" using this url:

mongodb://172.24.0.5:27017,172.24.0.3:27017,172.24.0.4:27017?replicaSet=dbrs

I am also sending my username and password, same that I am using in the compass connection url. The internal ips are correct, so that is not the problem.

So, basically, replicaset is up and running, I can connect from MongoDB Compass but I can't connect from my PHP code from a docker container in the same docker network.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment