Search code examples
mongodbdocker

Any container cannot connect to MongoDB Replica


I have configured a MongoDB replica set using Docker Compose, and it operates smoothly when accessed outside the Docker environment. However, I encounter an issue with mongodb-express, resulting in the error MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017.

Here's my Docker Compose configuration:

version: "3.9"

services:
  mongodb:
    image: mongo:7.0.7
    hostname: mongodb
    restart: always
    volumes:
      - ./scripts/mongodb/rs-initiate.js:/docker-entrypoint-initdb.d/rs-initiate.js
    ports:
      - 27017:27017
    networks:
      - default
    command: ["--replSet", "dbrs", "--bind_ip", "0.0.0.0"]
  
  mongodb-express:
    image: mongo-express
    restart: always
    depends_on:
      - mongodb
    environment:
      ME_CONFIG_MONGODB_URL: mongodb://mongodb:27017/?replicaSet=dbrs
    ports:
      - 8081:8081
    networks:
      - default

I've initialized the replica set using rs-initiate.js:

rs.initiate();

Additionally, when attempting to connect to MongoDB from a Docker container on the same network, I encounter the same issue. Here's an example of the container code:

pymongo.MongoClient("mongodb://mongodb:27017/?replicaSet=dbrs")
db = client["users"]
collection = db["messages"]
result = collection.find()

for i in result:
    print(i)

However, I receive the following error:

Could not reach any servers in [('127.0.0.1', 27017)]. Replica set is configured with internal hostnames
or IPs?, Timeout: 30s, Topology Description: <TopologyDescription id: 6601e73756219d127e813dcd,
topology_type: ReplicaSetNoPrimary, servers: [<ServerDescription ('127.0.0.1', 27017) server_type: Unknown,
rtt: None, error=AutoReconnect('127.0.0.1:27017: [Errno 111] Connection refused')>]>

Interestingly, the same code executes successfully when run locally on localhost:27017.

I appreciate any insights or suggestions to resolve this connectivity issue.


Solution

  • 🗎 scripts/rs-initiate.sh

    #!/bin/bash
    
    initialise() {
        while true
        do
            if mongosh --host mongodb --eval "quit()" &> /dev/null; then
                break
            fi
        done
        mongosh --host mongodb --eval "rs.initiate()"
    }
    
    initialise &
    
    mongod --replSet dbrs --bind_ip_all
    

    There are probably more elegant ways to do this, but it's a pragmatic solution.

    🗎 docker-compose.yml

    version: "3.9"
    
    services:
      mongodb:
        image: mongo:7.0.7
        container_name: mongo
        restart: always
        ports:
          - 27017:27017
        volumes:
          - ./scripts/rs-initiate.sh:/rs-initiate.sh
        command: ./rs-initiate.sh
    
      mongo-express:
        image: mongo-express
        container_name: mongo-express
        restart: always
        depends_on:
        - mongodb
        ports:
            - 8081:8081
        environment:
          ME_CONFIG_MONGODB_SERVER: mongodb
    

    enter image description here

    You can test a direct connection to MongoDB from the host using

    docker run --rm -it --network="host" mongo:7.0.7 mongosh
    

    Note that the name of the replica (dbrs) appears in the CLI prompt, confirming that you're connected to the right thing!

    enter image description here