How to connect to a mongodb replica set hosted locally in docker from the host machine

935 Views Asked by At

I want to create a local MongoDB replica set in docker so I can locally debug a program requiring mongo sessions/transactions. I have the following compose file to spin up the 3 required nodes. I also have a script that calls rs.initialize which is also below.

The servers initialize fine, but my connection using mongosh mongodb://localhost:27001,localhost:27002,localhost:27003/test?replicaSet=devReplicaSet fails.

Now the issue is that the hostnames and ports that the containers use to connect to each other are different than what the host machine uses to connect to them. So my seed connection works initially with the localhost hostname, then the replicaset connection protocol tries tells the client to connect to something like mongo1:27017 (as it is seen by the containers). However my host machine doesn't know how to resolve mongo1:27017, it knows it as localhost:27001 and the connection fails.

So how do I get the containers to forward me to this alternative address OR how do I give them all hostnames and ports they all understand no matter if it's from the host or container?

docker-compose.rs.yml

version: "3.9"
services:
  mongo1:
    hostname: 'mongo1'
    container_name: 'mongo1'
    image: mongo:5
    networks:
      - mongoCluster
    ports:
      - 27001:27017
    expose:
      - 27001
    entrypoint: mongod --replSet devReplicaSet --bind_ip localhost,mongo1
  mongo2:
    hostname: 'mongo2'
    container_name: 'mongo2'
    image: mongo:5
    networks:
      - mongoCluster
    ports:
      - 27002:27017
    expose:
      - 27001
    entrypoint: mongod --replSet devReplicaSet --bind_ip localhost,mongo2
    depends_on:
      - mongo1
  mongo3:
    hostname: 'mongo3'
    container_name: 'mongo3'
    image: mongo:5
    networks:
      - mongoCluster
    ports:
      - 27003:27017
    expose:
      - 27001
    entrypoint: mongod --replSet devReplicaSet --bind_ip localhost,mongo3
    depends_on:
      - mongo1
networks:
  mongoCluster:

The powershell script with rs.initialize

# Run docker compose up with docker-compose.repl.yml file
docker-compose -f docker-compose.repl.yml up -d

# Wait for 5 seconds
Start-Sleep -Seconds 5

# Run docker exec -it mongo1 mongosh
docker exec -it mongo1 mongosh --eval "rs.initiate({ `
    _id: 'devReplicaSet', `
    members: [ `
      {_id: 0, host: 'mongo1:27017'}, `
      {_id: 1, host: 'mongo2:27017'}, `
      {_id: 2, host: 'mongo3:27017'} `
    ] `
   })"
2

There are 2 best solutions below

2
Alex Blex On

The connection string mongodb://localhost:27001,localhost:27002,localhost:27003/test?replicaSet=devReplicaSet should agree with the replicaset config

members: [ 
  {_id: 0, host: 'mongo1:27017'}, 
  {_id: 1, host: 'mongo2:27017'}, 
  {_id: 2, host: 'mongo3:27017'} 
] 

the former uses host system domains, the latter uses docker-compose domains.

0
noshida_eto On

Same issue, solved by below: use extra_hosts instend of network_mode: host env: Macos

services:
  mongo1:
    container_name: mongo1
    hostname: mongo1
    image: mongo
    restart: always
    ports:
      - 27017:27017
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - "mongo1_data:/data/db"
      - "mongo1_config:/data/configdb"
    command: ["--replSet", "rs0", "--bind_ip_all", "--port", "27017"]

connecttion: mongodb://host.docker.internal:27017/db?replicaSet=rs0&retryWrites=true&w=majority