Reputation: 1257
I created 3 containers on docker for mongo:
docker pull mongo
docker network create mongo-cluster
docker run -d -p 27017:27017 --name m1 --net mongo-cluster mongo mongod --replSet mongo-rs
docker run -d -p 27018:27017 --name m2 --net mongo-cluster mongo mongod --replSet mongo-rs
docker run -d -p 27019:27017 --name m3 --net mongo-cluster mongo mongod --replSet mongo-rs
and setup a replica set:
docker exec -it m1 mongo
config = { "_id" : "mongo-rs", "members" : [ { "_id" : 0, "host" : "m1:27017" }, { "_id" : 1, "host" : "m2:27017" }, { "_id" : 2, "host" : "m3:27017" }] }
rs.initiate(config)
mongo-rs:PRIMARY>
> db.pets.insert({name : 'pet'})
WriteResult({ "nInserted" : 1 })
m1 is PRIMARY, m2 and m3 is SECONDARY
After insert a record to m1, I access to m2, m3 and see the recort inserted at m1 appear on m2, m3. It works
But when I try connect to mongodb with NodeJS, use mongoose:
mongoose.connect('mongodb://localhost:27018,localhost:27019,localhost:27020/tsng?replicaSet=mongo-rs', {
autoIndex: false,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
autoReconnect: true,
poolSize: 10,
bufferMaxEntries: 0,
useNewUrlParser: true,
useFindAndModify: false,
})
And an error has been throwed:
failed to connect to server [m3:27017] on first connect [Error: getaddrinfo ENOTFOUND m3
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:69:26) {
name: 'MongoNetworkError'
}]
And one more question, can I have an option to config if I connect to multiple mongodb like above, if one of mongodb is not start up or failed, NodeJS can still working on started mongodb ?
Upvotes: 2
Views: 170
Reputation: 5444
MongoDB replicaSet member discovery works by connecting to one of the members listed in the mongodb connection string then finding out by the replica members hostname configured in the replicaSet (the host names you initiated the replicaSet with).
from MongoDB docs on the matter (under host[:port]
):
For a replica set, specify the hostname(s) of the mongod instance(s) as listed in the replica set configuration.
That means the hostnames you give when you initiate the replicaSet are the ones you'll use to connect to it with.
My prefered solution is to create a docker-compose.yml
file configuring the mongodb cluster and the nodejs application, thuse making it easier to scale up and down, change configuration in a timely manner and with an added bonus it creates a docker network which lets you use the container or service names as DNS records in the docker network. here's a nice example of how to create such a setup. But in general here's a quick snippet:
version: "3"
services:
myawesomenodejsapplication:
container_name: myawesomenodejscontainer
image: my-awesome-nodejs-application-image
restart: on-failure
networks:
default:
depends_on:
- mongo1
- mongo2
- mongo3
mongo1:
hostname: mongo1
container_name: localmongo1
image: mongo
expose:
- 27017
ports:
- 27017:27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
mongo2:
hostname: mongo2
container_name: localmongo2
image: mongo
expose:
- 27017
ports:
- 27018:27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
mongo3:
hostname: mongo3
container_name: localmongo3
image: mongo
expose:
- 27017
ports:
- 27019:27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
and then to initialize the cluster with docker-compose you can (like specified in the example link added above):
docker-compose up -d
docker exec -it localmongo1 mongo
rs.initiate(
{
_id : 'rs0',
members: [
{ _id : 0, host : "mongo1:27017" },
{ _id : 1, host : "mongo2:27017" },
{ _id : 2, host : "mongo3:27017", arbiterOnly: true }
]
}
)
exit
And because we set up mongodb1-3 as the container hostnames we can use them to connect to the set.
Affcourse if you intend to one day move the cluster or change the configuration you'll need to change the set members hostnames accordingly
Upvotes: 1