I\'m trying to configure a mongodb replicaSet using docker-compose, but when I stop the master container it seems that it doesn\'t pass to the secondary.
red
I set up a gist with a guide on how to set it up using a docker-compose file and mongoose. https://gist.github.com/harveyconnor/518e088bad23a273cae6ba7fc4643549
Update: This does not work! You do need to run rs.initiate()
With MongoDB 4.0, you don't need a 4th container to run a setup script. It is really simple to bring up a replicaSet of 3 containers:
version: "3"
services:
mongo1:
hostname: mongo1
container_name: localmongo1
image: mongo:4.0-xenial
expose:
- 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
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
mongo3:
hostname: mongo3
container_name: localmongo3
image: mongo:4.0-xenial
expose:
- 27017
restart: always
entrypoint: [ "/usr/bin/mongod", "--bind_ip_all", "--replSet", "rs0" ]
More info here: https://github.com/msound/localmongo/tree/4.0
I had similar problem in setting replica set
up in a standalone mongodb
service with authentication and here are what I ended up with.
docker-compose.yml:
version: '3.7'
services:
...
db:
image: mongo
restart: always
expose:
- 27017
environment:
MONGO_INITDB_DATABASE: ${DATABASE_NAME}
MONGO_INITDB_ROOT_USERNAME: ${DATABASE_USER}
MONGO_INITDB_ROOT_PASSWORD: ${DATABASE_PASSWORD}
MONGO_REPLICA_SET_NAME: ${MONGO_REPLICA_SET_NAME}
command: ["--replSet", "${MONGO_REPLICA_SET_NAME}", "--bind_ip_all"]
healthcheck:
test: test $$(echo "rs.status().ok" | mongo -u $${MONGO_INITDB_ROOT_USERNAME} -p $${MONGO_INITDB_ROOT_PASSWORD} --quiet) -eq 1
interval: 10s
start_period: 30s
volumes:
- ./db:/data/db
- ./scripts/set-credentials.sh:/docker-entrypoint-initdb.d/set-credentials.sh
replica-setup:
image: mongo
restart: on-failure
networks:
default:
volumes:
- ./scripts/setup-replica.sh:/scripts/setup-replica.sh
entrypoint: [ "bash", "/scripts/setup-replica.sh" ]
depends_on:
- db
environment:
MONGO_INITDB_ROOT_USERNAME: ${DATABASE_USER}
MONGO_INITDB_ROOT_PASSWORD: ${DATABASE_PASSWORD}
./scripts/setup-replica.sh:
#!/bin/bash
MONGODB1=db
echo "Waiting for MongoDB startup..."
until curl http://${MONGODB1}:27017/serverStatus\?text\=1 2>&1 | grep uptime | head -1; do
printf '.'
sleep 1
done
# check if replica set is already initiated
RS_STATUS=$( mongo --quiet --host ${MONGODB1}:27017 -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD --eval "rs.status().ok" )
if [[ $RS_STATUS != 1 ]]
then
echo "[INFO] Replication set config invalid. Reconfiguring now."
RS_CONFIG_STATUS=$( mongo --quiet --host ${MONGODB1}:27017 -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD --eval "rs.status().codeName" )
if [[ $RS_CONFIG_STATUS == 'InvalidReplicaSetConfig' ]]
then
mongo --quiet --host ${MONGODB1}:27017 -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD <<EOF
config = rs.config()
config.members[0].host = db # Here is important to set the host name of the db instance
rs.reconfig(config, {force: true})
EOF
else
echo "[INFO] MongoDB setup finished. Initiating replicata set."
mongo --quiet --host ${MONGODB1}:27017 -u $MONGO_INITDB_ROOT_USERNAME -p $MONGO_INITDB_ROOT_PASSWORD --eval "rs.initiate()" > /dev/null
fi
else
echo "[INFO] Replication set already initiated."
fi
./scripts/set-credentials.sh:
#!/bin/bash
set -e
mongo -- "$MONGO_INITDB_DATABASE" <<EOF
var rootUser = '$MONGO_INITDB_ROOT_USERNAME';
var rootPassword = '$MONGO_INITDB_ROOT_PASSWORD';
var admin = db.getSiblingDB('admin');
admin.auth(rootUser, rootPassword);
var user = '$MONGO_INITDB_ROOT_USERNAME';
var password = '$MONGO_INITDB_ROOT_PASSWORD';
db.createUser({user: user, pwd: password, roles: ["readWrite"]});
EOF
What I achieved through is:
mongodb
service with username/password authentication for a default collectionreplica set
when it's first time running servicesreplica set
member when there's a previous db datamongodb
service by checking replica set
statusI would adivse you to have a look at khezen/mongo.
You can deploy a mongo replica set across a 3 nodes docker swarm with the following:
version: '3'
services:
replica1:
image: khezen/mongo:slim
deploy:
mode: replicated
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
palcement:
node.hostname: node-1
environment:
RS_NAME: shard1
SHARD_SVR: 'y'
AUTH: 'y'
volumes:
- /data/mongo/replica1:/data/db
networks:
- mongo_cluster
replica2:
image: khezen/mongo:slim
deploy:
mode: replicated
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
palcement:
node.hostname: node-2
environment:
RS_NAME: shard1
SHARD_SVR: 'y'
AUTH: 'y'
volumes:
- /data/mongo/replica2:/data/db
networks:
- mongo_cluster
replica3:
image: khezen/mongo:slim
deploy:
mode: replicated
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
palcement:
node.hostname: node-3
environment:
RS_NAME: shard1
SHARD_SVR: 'y'
MASTER: replica3
SLAVES: replica1 replica2
AUTH: 'y'
volumes:
- /data/mongo/replica3:/data/db
networks:
- mongo_cluster
networks:
mongo_cluster:
driver: overlay
disclaimer: I am the maintainer of this image.