User_Targaryen
User_Targaryen

Reputation: 4225

Docker compose for MongoDB ReplicaSet

I have been trying to dockerize my spring boot application which depends on redis, kafka and mongodb.

Following is the docker-compose.yml:

version: '3.3'
services:
  my-service:
    image: my-service
    build:
      context: ../../
      dockerfile: Dockerfile
    restart: always
    container_name: my-service
    environment:
      KAFKA_CONFLUENT_BOOTSTRAP_SERVERS: kafka:9092
      MONGO_HOSTS: mongodb:27017
      REDIS_HOST: redis
      REDIS_PORT: 6379

    volumes:
      - /private/var/log/my-service/:/var/log/my-service/
    ports:
      - 8080:8090
      - 1053:1053

    depends_on:
      - redis
      - kafka
      - mongodb

  portainer:
    image: portainer/portainer
    command: -H unix:///var/run/docker.sock
    restart: always
    container_name: portainer
    ports:
      - 9000:9000
      - 9001:8000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  redis:
    image: redis
    container_name: redis
    restart: always
    ports:
      - 6379:6379

  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - 2181:2181
    container_name: zookeeper

  kafka:
    image: wurstmeister/kafka
    ports:
      - 9092:9092
    container_name: kafka
    environment:
      KAFKA_CREATE_TOPICS: "cms.entity.change:1:1" # topic:partition:replicas
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_PORT: 9092
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - "zookeeper"

  mongodb:
    image: mongo:latest
    container_name: mongodb
    environment:
      MONGO_INITDB_ROOT_USERNAME:
      MONGO_INITDB_ROOT_PASSWORD:
    ports:
      - 27017:27017
    volumes:
      - ./data/db:/data/db

The issue is that this starts up mongo as a STANDALONE instance. So the APIs in my service that persist data are failing as mongo needs to start as a REPLICA_SET.

How can I edit my docker-compose file to start mongo as a REPLICA_SET?

Upvotes: 1

Views: 1640

Answers (2)

sbp
sbp

Reputation: 963

I had the same issue and ended up on this stackoverflow post.

We had a requirement of using official mongoDB docker image (https://hub.docker.com/_/mongo ) and couldn't use bitnami as suggested in Vahid's answer.

This answer isn't exactly what's needed by the question asked and coming in 6 months too late; but it should give directions to someone who need to use the mongoDb standalone replicaset throw away instance for integration testing purpose. If you need to use it in PROD then you'll have to provide environment variables for volumes and auth as per Vahid's answer.

version: '3.7'
services:
  mongodb:
    image: mongo:latest
    container_name: myservice-mongodb
    networks:
      - myServiceNetwork
    expose:
      - 27017
    command: --replSet singleNodeReplSet
  mongodb-replicaset:
    container_name: mongodb-replicaset-helper
    depends_on:
      - mongodb
    networks:
      - myServiceNetwork
    image: mongo:latest
    command: bash -c "sleep 5 && mongo --host myservice-mongodb --port 27017 --eval \"rs.initiate()\" && sleep 2 && mongo --host myservice-mongodb --port 27017 --eval \"rs.status()\" && sleep infinity"
  my-service:
    depends_on:
      - mongodb-replicaset
    image: myserviceimage
    container_name: myservicecontainer
    networks:
      - myServiceNetwork
    environment:
      myservice__Database__ConnectionString: mongodb://myservice-mongodb:27017/?connect=direct&replicaSet=singleNodeReplSet&readPreference=primary
      myservice__Database__Name: myserviceDb

networks:
  myServiceNetwork:
    driver: bridge

NOTE: Please look at the way how connection string is passed as env variable to the service depending on mongo replicaset instance. You'd have to ensure that the name used in setting up the mongodb replicaset (in my case singleNodeReplicaSet) is passed on to the service depending on it.

Upvotes: 3

Vahid
Vahid

Reputation: 1417

Edited: my previous answer was far wrong so I changed it. I managed to make it work using 'bitnami/mongodb:4.0'. Not sure if that would help you or not, but maybe it gives you some idea. They have a docker-compose file ready for replicaset mode.

version: '3'

services:
  mdb-primary:
    image: 'bitnami/mongodb:4.0'
    environment:
      - MONGODB_REPLICA_SET_MODE=primary
      - MONGODB_ROOT_PASSWORD=somepassword
      - MONGODB_REPLICA_SET_KEY=replicasetkey
      - MONGODB_ADVERTISED_HOSTNAME=mdb-primary

  mdb-secondary:
    image: 'bitnami/mongodb:4.0'
    depends_on:
      - mdb-primary
    environment:
      - MONGODB_PRIMARY_HOST=mdb-primary
      - MONGODB_REPLICA_SET_MODE=secondary
      - MONGODB_PRIMARY_ROOT_PASSWORD=somepassword
      - MONGODB_REPLICA_SET_KEY=replicasetkey
      - MONGODB_ADVERTISED_HOSTNAME=mdb-secondary

  mdb-arbiter:
    image: 'bitnami/mongodb:4.0'
    depends_on:
      - mdb-primary
    environment:
      - MONGODB_PRIMARY_HOST=mdb-primary
      - MONGODB_REPLICA_SET_MODE=arbiter
      - MONGODB_PRIMARY_ROOT_PASSWORD=somepassword
      - MONGODB_REPLICA_SET_KEY=replicasetkey
      - MONGODB_ADVERTISED_HOSTNAME=mdb-arbiter 

  mongo-cli:
    image: 'bitnami/mongodb:latest'

don't forget to add volumes and map it to /bitnami on the primary node

the last container, mongo-cli is for testing purposes. So you can connect to the replicaset using the cli, there is an argument about that here if you like to read about it.

$ docker-compose exec mongo-cli bash
$ mongo "mongodb://mdb-primary:27017/test?replicaSet=replicaset"

Upvotes: 0

Related Questions