4

I would like to start this MongoDB Replica Set:

version: "3"

services:
  mongo1:
    image: mongo
    ports:
      - 27017:27017
    command: mongod --replSet rs0
  mongo2:
    image: mongo
    ports:
      - 27018:27017
    command: mongod --replSet rs0
  mongo3:
    image: mongo
    ports:
      - 27019:27017
    command: mongod --replSet rs0

Wait for those to come up, then access the Mongo shell via terminal:

docker exec -it mongo1 mongo

Then in Mongo shell do:

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

Mongo also allows mongo --eval "rs.initiate(..)", which may make things easier.

My question is how do I run this command after mongo1, mongo2, mongo3 are up?

2
  • What happens when you run this? I imagine you could set a container_name to make it easier? Commented May 25, 2018 at 22:45
  • It works if I just do it manually like that but I would like it to be automated to be deployed to the cloud. Commented May 25, 2018 at 23:33

2 Answers 2

3

You can do this, I recently had to run mongo --repair then run the MongoDB itself and after the MongoDB is up I needed to add my user to the DB, you can easily change things to run commands only after all three MongoDBs are up.

Possible docker-compose.yml:

version: "2"
services:
  mongo:
    container_name: mongo
    restart: on-failure:10
    image: mongo
    environment:
      - MONGO_INITDB_ROOT_USERNAME=<user>
      - MONGO_INITDB_ROOT_PASSWORD=<pass>
      - MONGO_INITDB_DATABASE=db
    volumes:
      - ./data:/data/db
    ports:
      - "27017:27017"
    command: bash -c "mongod --repair && mongod"

  mongoClient:
    image: mongo
    container_name: mongoClient
    links:
      - mongo
    volumes:
      - ./deployment_scripts:/deployment_scripts
    command: 
      - /deployment_scripts/add_user.sh
    depends_on:
      - mongo

  app:
    container_name: app
    restart: always
    build: .
    volumes:
      - .:/usr/src/app
    ports:
      - "3000:3000"
    depends_on:
      - mongoClient
    links:
      - mongo

My /deployment_scripts/add_user.sh script wait for MongoDB to be up:

until mongo --host mongo --eval "print(\"waited for connection\")"
do
    sleep 1
done

// you can add more MongoDB waits here

echo "Adding user to MongoDB..."
mongo --host mongo --eval "db.createUser({ user: \"<user>\", pwd: \"<pass>\", roles: [ { role: \"root\", db: \"admin\" } ] });"
echo "User added."

Note that you can address all three of your MongoDBs by replacing --host mongo with your --host mongo1 --host mongo2 and --host mongo3. You'll use this for both of the eval commands in the script.

Credit to this SO answer https://stackoverflow.com/a/45060399/4295037 that I used (until mongo ...).

Sign up to request clarification or add additional context in comments.

Comments

-1

I assume you are using Oficial Mongo image, that image is configured with:

ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["mongod"]

If you check the docker-entrypoint.sh you will notice you could run any command you want by overwriting the CMD.

So, you can do for each mongo container

$ docker run -d mongo
9bf0473d491a2d7ae821bcf10ed08cd49678d28e46344589622bd9440a6aca65

$ docker ps -q
9bf0473d491a

$ docker exec -ti 9bf0473d491a mongo --eval "rs.initiate(.....)"
MongoDB shell version v3.6.5
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.5
{
    "ok" : 0,
    "errmsg" : "This node was not started with the replSet option",
    "code" : 76,
    "codeName" : "NoReplicationEnabled"
}

Notice that the errmsg is just because in my example the rs.initiate() is empty, it will work for you with the right config.

3 Comments

Hi there. I am sorry for the stupid question, but what exactly am I supposed to edit? Do you mean pull the image, edit the image, then commit my modified image? I was hoping I could just stick an easy command in my docker-compose somehow. Also I was just trying to do rs.initiate(...) once after all replicas are up, not for each replica.
@kaya I don't think mongo images are configurable in that sense using just docker-compose. I would advise using docker exec to configure after deployment. My guess is it would take some extensive work to be able to dynamically add a MongoDB Replica set using just docker-compose configuration.
@kayla , edit the rs.initiate(...) and replace the ... with your own json config to initiate the RS.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.