This will guide you through setting up a replica set in a docker environment using.
- Docker Compose
- MongoDB Replica Sets
- Mongoose
- Mongoose Transactions
Thanks to https://gist.github.com/asoorm for helping with their docker-compose file!
This will guide you through setting up a replica set in a docker environment using.
Thanks to https://gist.github.com/asoorm for helping with their docker-compose file!
mongo-setup: | |
container_name: mongo-setup | |
image: mongo | |
restart: on-failure | |
networks: | |
default: | |
volumes: | |
- ./scripts:/scripts | |
entrypoint: [ "/scripts/setup.sh" ] # Make sure this file exists (see below for the setup.sh) | |
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", "--journal", "--dbpath", "/data/db", "--enableMajorityReadConcern", "false" ] | |
volumes: | |
- <VOLUME-DIR>/mongo/data1/db:/data/db # This is where your volume will persist. e.g. VOLUME-DIR = ./volumes/mongodb | |
- <VOLUME-DIR>/mongo/data1/configdb:/data/configdb | |
mongo2: | |
hostname: mongo2 | |
container_name: localmongo2 | |
image: mongo | |
expose: | |
- 27017 | |
ports: | |
- 27018:27017 | |
restart: always | |
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0", "--journal", "--dbpath", "/data/db", "--enableMajorityReadConcern", "false" ] | |
volumes: | |
- <VOLUME-DIR>/mongo/data2/db:/data/db # Note the data2, it must be different to the original set. | |
- <VOLUME-DIR>/mongo/data2/configdb:/data/configdb | |
mongo3: | |
hostname: mongo3 | |
container_name: localmongo3 | |
image: mongo | |
expose: | |
- 27017 | |
ports: | |
- 27019:27017 | |
restart: always | |
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0", "--journal", "--dbpath", "/data/db", "--enableMajorityReadConcern", "false" ] | |
volumes: | |
- <VOLUME-DIR>/mongo/data3/db:/data/db | |
- <VOLUME-DIR>/mongo/data3/configdb:/data/configdb |
# NOTE: This is the simplest way of achieving a replicaset in mongodb with Docker. | |
# However if you would like a more automated approach, please see the setup.sh file and the docker-compose file which includes this startup script. | |
# run this after setting up the docker-compose This will instantiate the replica set. | |
# The id and hostname's can be tailored to your liking, however they MUST match the docker-compose file 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 |
// If on a linux server, use the hostname provided by the docker compose file | |
// e.g. HOSTNAME = mongo1, mongo2, mongo3 | |
// If on MacOS add the following to your /etc/hosts file. | |
// 127.0.0.1 mongo1 | |
// 127.0.0.1 mongo2 | |
// 127.0.0.1 mongo3 | |
// And use localhost as the HOSTNAME | |
mongoose.connect('mongodb://<HOSTNAME>:27017,<HOSTNAME>:27018,<HOSTNAME>:27019/<DBNAME>', { | |
useNewUrlParser : true, | |
useFindAndModify: false, // optional | |
useCreateIndex : true, | |
replicaSet : 'rs0', // We use this from the entrypoint in the docker-compose file | |
}) |
#!/bin/bash | |
#MONGODB1=`ping -c 1 mongo1 | head -1 | cut -d "(" -f 2 | cut -d ")" -f 1` | |
#MONGODB2=`ping -c 1 mongo2 | head -1 | cut -d "(" -f 2 | cut -d ")" -f 1` | |
#MONGODB3=`ping -c 1 mongo3 | head -1 | cut -d "(" -f 2 | cut -d ")" -f 1` | |
MONGODB1=mongo1 | |
MONGODB2=mongo2 | |
MONGODB3=mongo3 | |
echo "**********************************************" ${MONGODB1} | |
echo "Waiting for startup.." | |
until curl http://${MONGODB1}:27017/serverStatus\?text\=1 2>&1 | grep uptime | head -1; do | |
printf '.' | |
sleep 1 | |
done | |
# echo curl http://${MONGODB1}:28017/serverStatus\?text\=1 2>&1 | grep uptime | head -1 | |
# echo "Started.." | |
echo SETUP.sh time now: `date +"%T" ` | |
mongo --host ${MONGODB1}:27017 <<EOF | |
var cfg = { | |
"_id": "rs0", | |
"protocolVersion": 1, | |
"version": 1, | |
"members": [ | |
{ | |
"_id": 0, | |
"host": "${MONGODB1}:27017", | |
"priority": 2 | |
}, | |
{ | |
"_id": 1, | |
"host": "${MONGODB2}:27017", | |
"priority": 0 | |
}, | |
{ | |
"_id": 2, | |
"host": "${MONGODB3}:27017", | |
"priority": 0 | |
} | |
],settings: {chainingAllowed: true} | |
}; | |
rs.initiate(cfg, { force: true }); | |
rs.reconfig(cfg, { force: true }); | |
rs.slaveOk(); | |
db.getMongo().setReadPref('nearest'); | |
db.getMongo().setSlaveOk(); | |
EOF |
async function transaction() { | |
// Start the transaction. | |
const session = await ModelA.startSession(); | |
session.startTransaction(); | |
try { | |
const options = { session }; | |
// Try and perform operation on Model. | |
const a = await ModelA.create([{ ...args }], options); | |
// If the first operation succeeds this next one will get called. | |
await ModelB.create([{ ...args }], options); | |
// If all succeeded with no errors, commit and end the session. | |
await session.commitTransaction(); | |
session.endSession(); | |
return a; | |
} catch (e) { | |
// If any error occured, the whole transaction fails and throws error. | |
// Undos changes that may have happened. | |
await session.abortTransaction(); | |
session.endSession(); | |
throw e; | |
} | |
} |