Two containers can't communicate (webserver and MongoDB)

Hello everyone,

I’m currently facing an issue with communication between two containers in the same Docker network. One container is running Webserver.js, and the other one hosts MongoDB. Unfortunately, they don’t seem to be communicating, the console always prints the error: connect ECONNREFUSED 127.0.0.1:27017.

What puzzles me is that I explicitly specify the IP address of the container, but get an issue with 127.0.0.1 (localhost) mentioned, why ? Here’s an example of what I’m trying:

var url_db = 'mongodb://admin:admin@mongodb:27017/thal';

var url_db = 'mongodb://admin:admin@172.18.0.11:27017/thal';

If anyone could help me identify a solution to this problem, it would be a fantastic Christmas present! :slight_smile:

Thank you in advance !
tutoy83

Based on that you tried with a static IP address and the fact that you shared nothing Docker-related, but you shared a probably nodejs code, are you sure it is a Docker issue?

I understand that the webserver runs in Docker a container, but since it didn’t matter when you replaced the placeholder with an IP, it looks like that config is not used at all.

Hello @rimelek ,

Regarding docker, there are just two containers built in the docker compose yml :grinning:
Looks to be a Docker issue because, when I run both side in my Debian terminal (with local host), everything works.

The two lines above are extracted from my WebServer.js that runs in a container and tries to connect to another one.
But the error message is related to local host… strange
I tried most solutions on Forum.

Can you share the compose file and the code that actually connects to the database using the variable? People often don’t realize how much that could matter and help to understand the issue or trying to find the issue in another direction.

That’s the point. You had only one environment and now you had to create two. There could be mistakes in the process.

In my experience, when an error message says “A” while you expect “B”, the answer is not “B was magically converted to A”, but you miss something and “A” was always there.

Docker will not do anything with your config so your next job seems to be to find out where that localhost is coming from. And that is unlikely to be coming from Docker directly. It could be any kind of cache or even a built-in behavior to always connect to localhost and it just worked on localhost because it would have been conneced to that anyway.

When you see 127.0.0.1 in error message, then there is probably something wrong how you pass the URL to you client, that’s the default address.

And 127.0.0.1 will not work, as every container has their own 127.0.0.1 address.

Hello both of you,

Here are the code:

version: '3.3'

services:
  data-service:
    build: .
    ports:
      - "8092:8092"
    depends_on:
      - mongo
    networks:
      ycnet:
        ipv4_address: 172.11.0.8

  mongo:
    image: mongo:7.0
    restart: always
    container_name: mongo
    ports:
      - "27017:27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: admin
      MONGO_INITDB_ROOT_PASSWORD: admin
      MONGO_INITDB_DATABASE: yc_data_service
    volumes:
      - ./db_data/:/data/db/
      - /etc/timezone:/etc/timezone:ro
    networks:
      ycnet:
        ipv4_address: 172.11.0.7

  mongo-express:
    image: mongo-express
    restart: always
    container_name: mongo-express
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: admin
      ME_CONFIG_MONGODB_ADMINPASSWORD: admin
      ME_CONFIG_MONGODB_URL: mongodb://admin:admin@mongo:27017/
    networks:
      ycnet:
        ipv4_address: 172.11.0.9

# ------------------------------------
# NETWORKS
# ------------------------------------

networks:
  ycnet:
    name: ycnet
    external: true

extract of the config.ts:

export const config = {
    
    PORT: env.PORT ? parseInt(env.PORT) : 8092,

    DB_CONN_STRING: env.DB_CONN_STRING ? env.DB_CONN_STRING : "mongodb://admin:admin@172.11.0.7:27017/",

    DB_NAME: env.DB_NAME ? env.DB_NAME : "yc_data_service",

    DB_CLIENT_SAMPLES_COLLECTION: env.DB_CLIENT_SAMPLES_COLLECTION ? env.DB_CLIENT_SAMPLES_COLLECTION : "client_samples",

Kind regards,

Thank you, but it shows only the variables, not where the connection actually happens

Just to give you an workaround in case you can’t solve the original issue soon, you can share the network namespaces between the containers. Just the relevant parts of the compose file showing the network mode

version: '3.3'

services:
  data-service:
    build: .
    ports:
      - "8092:8092"
    depends_on:
      - mongo
    network_mode: service:mongo

  mongo:
    image: mongo:7.0
    # ...

You probably don’t want it if a local user has more privileges in mongodb than a remote user, but this is an option too.

Here is Database.ts file :slight_smile:

const { MongoClient } = require('mongodb');

export class Database {

    private static client = new MongoClient(config.DB_CONN_STRING);
    private static database = null;

    public static async connect() {
        log.info("Connecting to mongo");
        await this.client.connect();
        this.database = this.client.db(config.DB_NAME);      
        log.info(`Successfully connected'`);
    }

    public static getDatabase = () => Database.database as typeof MongoClient;
    
}

What if you change the following line in the config:

to this:

    DB_CONN_STRING: "mongodb://admin:admin@172.11.0.7:27017/",

So it is using it regardless of what the value of env.DB_CONN_STRING is.

I have already tried. :neutral_face:

Why do you use fixed IP addresses? Docker provides IP management and an internal DNS server. Usually it works very well and fully automatic, just access the other service in the Docker network by the service name.

And for plain NodeJS debugging, maybe try

log.info("Connecting to mongo", config.DB_CONN_STRING);

I have 6 containers in all the project that are communicating each other in the same network but with just their name, it doesn’t work. IP addr are working well except for this case.

Hi @bluepuma77 ,
After running npx tsc to build .ts file I get the following Database.js

    static connect() {
        return __awaiter(this, void 0, void 0, function* () {
            Logger_1.log.info("Connecting to mongo database...", config_1.config.DB_CONN_STRING);
            yield this.client.connect();

Here is what I get

 2024-01-04 09:35:40.965  INFO  [dist/core/Database.js:36 Function.<anonymous>] Connecting to mongo database... 
/opt/app/node_modules/mongodb/lib/sdam/topology.js:292
const timeoutError = new error_1.MongoServerSelectionError(`Server selection timed out after ${serverSelectionTimeoutMS} ms`, this.description);
                                     ^

MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27057
    at Timeout._onTimeout (/opt/app/node_modules/mongodb/lib/sdam/topology.js:292:38)

I don’t see the DN_CONN_STRING in log.info. Looks like it’s not taken into account.

@rimelek Can you please contact me in DM or mail for a moderation related question ?

When using

  data-service:
    build: .
    ports:
      - "8092:8092"
    depends_on:
      - mongo
    network_mode: service:mongo

I get Error response from daemon: conflicting options: port publishing and the container type network mode

and I would prefer each service to have a static IP addr assigned.

yeahh !

Problem solved, look it was a problem of files versions that were build with the docker compose build command.

2024-01-04 09:55:32.214 INFO [dist/core/Database.js:39 Function.<anonymous>] Successfully connected to database

with DB_CONN_STRING: env.DB_CONN_STRING ? env.DB_CONN_STRING : "mongodb://admin:admin@172.11.0.7:27017/",
in the config.ts

Thanks guy

When using another container’s network namespace, ports must published on the container that uses the bridge network and not another container’s network namespace. It was just an alternative option though. I totally get that you prefer not to share network namespaces.

It is good to see you found a solution! :slight_smile: