Mongodb cannot connect to Docker Host machine

So I have been scratching my head on this for a while but did not find any solution anywhere. I’m running a node v18 express application on docker and I’m trying to connect to mongodb that is running on my host machine and not in the docker container. I was able to connect to redis and memcached in similar way using host.docker.internal. Redis and memcached also running on host machine and not on the container.

I thought it was issue from mondb node version, so I updated it from node 12 to node 18 after wards, but still the issue persisted.

My mongodb connection string is

“mongodb://userName:password@docker.host.internal:27017/?ssl=false&replicaSet=replicaSetName”
“mongodb://userName:password@127.0.0.1:27017/?ssl=false&replicaSet=replicaSetName”
“mongodb://userName:password@192.168.29.160:27017/?ssl=false&replicaSet=replicaSetName”

In all the three URIs that I used, I got the same error evertime

backend-backend-1 | MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
backend-backend-1 | at Timeout._onTimeout (/usr/src/app/node_modules/mongodb/lib/sdam/topology.js:277:38)
backend-backend-1 | at listOnTimeout (node:internal/timers:569:17)
backend-backend-1 | at process.processTimers (node:internal/timers:512:7) {
backend-backend-1 | reason: TopologyDescription {
backend-backend-1 | type: ‘ReplicaSetNoPrimary’,
backend-backend-1 | servers: Map(1) { ‘127.0.0.1:27017’ => [ServerDescription] },
backend-backend-1 | stale: false,
backend-backend-1 | compatible: true,
backend-backend-1 | heartbeatFrequencyMS: 10000,
backend-backend-1 | localThresholdMS: 15,
backend-backend-1 | setName: ‘rs0’,
backend-backend-1 | maxElectionId: new ObjectId(“7fffffff0000000000000023”),
backend-backend-1 | maxSetVersion: 1,
backend-backend-1 | commonWireVersion: 0,
backend-backend-1 | logicalSessionTimeoutMinutes: null
backend-backend-1 | },
backend-backend-1 | code: undefined,
backend-backend-1 | [Symbol(errorLabels)]: Set(0) {}
backend-backend-1 | }

But I could not understand why it is always trying to connect to 127.0.0.1 when I passed a different IP as well.

I’m able to run the app easily without docker, but using docker, MongoDB is not able to resolve the correct IP even when provided different IP as well.

1 Like

Most likely your code is wrong and it is not using your configured connection string. You will need to share your code where you establish the connection to the server.

this is my code and I’m running await MongoDB.disconnectDB(); in my index file

const { uri } = conf.db;
const connectDB = async () => {
// eslint-disable-next-line no-useless-catch
try {
console.log(‘uri===’, uri);
db = await MongoClient.connect(uri, options);
return db;
} catch (err) {
throw err;
}
};

backend-backend-1 | System Initialization started with DEVELOPMENT config
backend-backend-1 | uri=== mongodb://buyucoinUser:Pass123@192.168.29.160:27017/buyucoin_stagin?ssl=false&replicaSet=rs0
backend-backend-1 | (node:149) Warning: Accessing non-existent property ‘UserModel’ of module exports inside circular dependency
backend-backend-1 | (Use node --trace-warnings ... to show where the warning was created)
backend-backend-1 | (node:149) NOTE: We are formalizing our plans to enter AWS SDK for JavaScript (v2) into maintenance mode in 2023.
backend-backend-1 |
backend-backend-1 | Please migrate your code to use AWS SDK for JavaScript (v3).
backend-backend-1 | For more information, check the migration guide at Migrating your code to SDK for JavaScript V3 - AWS SDK for JavaScript
backend-backend-1 | System Initialization error
backend-backend-1 | MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
backend-backend-1 | at Timeout._onTimeout (/usr/src/app/node_modules/mongodb/lib/sdam/topology.js:277:38)
backend-backend-1 | at listOnTimeout (node:internal/timers:569:17)
backend-backend-1 | at process.processTimers (node:internal/timers:512:7) {
backend-backend-1 | reason: TopologyDescription {
backend-backend-1 | type: ‘ReplicaSetNoPrimary’,
backend-backend-1 | servers: Map(1) { ‘127.0.0.1:27017’ => [ServerDescription] },
backend-backend-1 | stale: false,
backend-backend-1 | compatible: true,
backend-backend-1 | heartbeatFrequencyMS: 10000,
backend-backend-1 | localThresholdMS: 15,
backend-backend-1 | setName: ‘rs0’,
backend-backend-1 | maxElectionId: new ObjectId(“7fffffff0000000000000023”),
backend-backend-1 | maxSetVersion: 1,
backend-backend-1 | commonWireVersion: 0,
backend-backend-1 | logicalSessionTimeoutMinutes: null
backend-backend-1 | },
backend-backend-1 | code: undefined,
backend-backend-1 | [Symbol(errorLabels)]: Set(0) {}
backend-backend-1 | }
backend-backend-1 | Process exited with code 1
backend-backend-1 | [nodemon] app crashed - waiting for file changes before starting…

This is the exact console with everything
@ steevej

Try to connect to the same URI with Compass or mongosh.

Try removing the replicaSet=rs0 from your connection string.

Are you really using mongod or AWS DynamoDB?

Please share the output of docker ps.

1 Like

@Devesh_Aggrawal,

But I could not understand why it is always trying to connect to 127.0.0.1 when I passed a different IP as well.

Chances are you configured your replica set with the hosts pointing to 127.0.0.1. As a result, once you connect using a connection string such as mongodb://buyucoinUser:Pass123@192.168.29.160:27017/buyucoin_stagin?ssl=false&replicaSet=rs0 the first thing that will happen is the driver will attempt to discover the replica set and will get a list of hosts back using those “internal” hosts/IPs - not what you passed in the connection string.

The easiest way to validate this is to connect to the replica set using the mongosh shell and run rs.status()

This will output an array of members in the set that includes details such as the state of the member (PRIMARY, SECONDARY … etc) and the name. The name here is the host/port for that node.

Assuming you have your mapped to either 127.0.0.1 or localhost (like the example above), you can fix this by reconfiguring the replica set.

As an example, let’s say you have 3 members on ports 27017, 27018 and 27019. If you wanted to configure the replica set to map these nodes to those ports on IP address 192.168.29.160, from the mongosh shell you would do the following:

var c = rs.config();
c.members[0].host = "192.168.29.160:27017";
c.members[1].host = "192.168.29.160:27018";
c.members[2].host = "192.168.29.160:27019";
rs.reconfig(c);

Once the replica set is reconfigured, when your application connects next it will discover the replica set members and try to connect to them on the host/port pairs that you configured above.

1 Like

If I try to connect with the same URI without docker, I’m able to easily connect with nodejs driver as well and robo mongo also.

If I remove replicaSet=rs0 then without using docker I’m able to connect, but using docker still the same error

I’m using mongodb-community@4.4 on macbook

Below is the docker ps response

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fe5ecd3ece2d backend-backend “docker-entrypoint.s…” 7 seconds ago Up 6 seconds 5001/tcp, 0.0.0.0:8000->8000/tcp backend-backend-1

@ steevej

@ alexbevi

You are right, using rs.status() members are shown as below

“members” : [
{
“_id” : 0,
“name” : “127.0.0.1:27017”,
“health” : 1,
“state” : 1,
“stateStr” : “PRIMARY”,
“uptime” : 55830,
“optime” : {
“ts” : Timestamp(1678103836, 1),
“t” : NumberLong(35)
},
“optimeDate” : ISODate(“2023-03-06T11:57:16Z”),
“syncSourceHost” : “”,
“syncSourceId” : -1,
“infoMessage” : “”,
“electionTime” : Timestamp(1678048011, 1),
“electionDate” : ISODate(“2023-03-05T20:26:51Z”),
“configVersion” : 1,
“configTerm” : 35,
“self” : true,
“lastHeartbeatMessage” : “”
}
],

So I used 192.168.29.160 because this is the IP on which my macbook is available on the local wifi. So I tried the same thing without using docker and I was able to connect to the mongo without any issue, but if I try to connect to mongo of host machine from docker container, then this issue persists

@Devesh_Aggrawal you may need to update the IP Binding info for your mongod. For example, starting a node with mongod --port 27017 ... will only bind to localhost and listen on port 27017.

Using mongod --port 27017 --bind_ip_all will bind to all IPv4/v6 addresses. For local testing this may be the easiest way to get this sorted out, but if you’re managing a production cluster I’d recommend configuring your IP bindings a bit more restrictively :wink:

@ alexbevi

I’m already using binding all ipv4 and ipv6 in the configuration
mongo.conf is below

systemLog:
destination: file
path: /opt/homebrew/var/log/mongodb/mongo.log
logAppend: true
storage:
dbPath: /opt/homebrew/var/mongodb
replication:
replSetName: “rs0”
net:
bindIp: ::,0.0.0.0

@Devesh_Aggrawal this is not a MongoDB question, but a question of configuring Docker networks. I’ll let someone else weigh in but it sounds like you may need to setup a bridge network to ensure you can access your local network from the docker network layer.

Not by forte, and it sounds like the default bridge should work as you expect so I’ll defer to someone else.

Having had to go through this recently, and assuming that it is possible to connect to mongod using mongosh with your connection string, because you have forwarded the container port to your host machine when starting mongod as a docker container, what you may be missing is specifying a directConnection

Try adding &directConnection=True to your connection URL.