Deploy mongodb replicaset servers with Docker on different physical servers
docker, mongodb
Solution
Let's assume:
- you have 3 different docker hosts (servers), with IPs `10.1.1.101`, `10.1.1.102`, `10.1.1.103`
- want to deploy a single replica set called `rsacommeassure`
- `Dockerfile`s for mongodb expose port 27017
- all servers are in a trusted zone and can talk to each other
First let's start mongodb containers on each server (`10.1.1.101 ~$` is used for command prompt):
10.1.1.101 ~$ docker run -d -p 27017:27017 --name mongodbmycompany1 dockerfile/mongodb mongod --replSet rsacommeassure
10.1.1.102 ~$ docker run -d -p 27017:27017 --name mongodbmycompany2 dockerfile/mongodb mongod --replSet rsacommeassure
10.1.1.103 ~$ docker run -d -p 27017:27017 --name mongodbmycompany3 dockerfile/mongodb mongod --replSet rsacommeassure
`-p 27017:27017` exposes port 27017 on the host IP so mongo is accessible on servers' host IP address.
Then you need to initiate the replica set, so just run this against a mongodb container (I'll pick server1 here):
your_laptop ~$ > mongo --host 10.1.1.101
MongoDB shell version: 2.6.9
connecting to: test
> rs.initiate()
> cfg = rs.conf()
> cfg.members[0].host = "10.1.1.101:27017"
> rs.reconfig(cfg)
> rs.add("10.1.1.102:27017")
> rs.add("10.1.1.103:27017")
> rs.status();
The IPs are local but it works with global as well as long as the servers can talk to each other (VPN, firewall, DMZ, whatever). Btw you should consider security carefully.
Problem
I'm trying to deploy a mongodb replicaset using docker. I managed to do it on a same server by executing this : ``` docker run -d --expose 27017 --name mongodbmycompany1 dockerfile/mongodb mongod --replSet rsmycompa docker run -d --expose 27017 --name mongodbmycompany2 dockerfile/mongodb mongod --replSet rsacommeassure docker run -d --expose 27017 --name mongodbmycompany3 dockerfile/mongodb mongod --replSet rsacommeassure MONGODB1=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongodbmycompany1) MONGODB2=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongodbmycompany2) MONGODB3=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongodbmycompany3) echo $MONGODB1 echo $MONGODB2 echo $MONGODB3 echo "Mongodb Replicaset init" docker exec mongodbmycompany1 mongo 127.0.0.1:27017/mycompany --eval 'if(!rs.conf()) { rs.initiate(); cfg = rs.conf(); cfg.members[0].host = "'$MONGODB1':27017"; rs.reconfig(cfg); rs.add("'$MONGODB2':27017"); rs.add("'$MONGODB3':27017"); } rs.status();' ``` It's working as expected. My replicaset is initialized and my mongodb resultset config contains my 3 servers identified by their internal IP address. It's not perfect as I'd prefer to use servers names but I didn't manage to do it. Docker only populate each /etc/hosts file with servers names passed at image launch with --link parameter. If i add a new server while others are running. Those servers won't ping the new server. Now I have another question. In production, having a lot of Mongodb docker image running on a same physical server is possible but it's not safe : - if my physical server falls down, i lose all my Mongodb replicas and my service is down - if my physical server uses internal storage, all my docker images use the same disk... and I'm going to have IO problems. So my question is : How can I deploy many mongodb replicas on multiple physical servers ? How those mongodb replicas can communicate with each others (primary and secondaries servers can change) while they are on different servers or even on different datacenters ?