Local MQTT mosquitto instance getting connect ECONNREFUSED 127.0.0.1:1883

Viewed 11844

I am trying to run a local mosquitto broker, publisher and subscriber setup via docker and docker-compose, but the publisher cannot connect to the broker. However, connecting to local broker via cli works fine. Getting following error when running below setup.

{ Error: connect ECONNREFUSED 127.0.0.1:1883
  at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1088:14)
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 1883 }

Local dockerized setup:

docker-compose.yml:

version: "3.5"

services:
  publisher:
    hostname: publisher
    container_name: publisher
    build:
      context: ./
      dockerfile: dev.Dockerfile
    command: npm start
    networks:
      - default
    depends_on:
      - broker

  broker:
    image: eclipse-mosquitto
    hostname: mosquitto-broker
    container_name: mosquitto-broker
    networks:
      - default
    ports:
      - "1883:1883"

networks:
  default:

dev.Dockerfile:

FROM node:11-alpine

RUN mkdir app
WORKDIR app

COPY package*.json ./

RUN npm ci

COPY ./src ./src

CMD npm start

src/index.js:

const mqtt = require("mqtt");

const client = mqtt.connect("mqtt://localhost:1883");

client.on("connect", () => {
  console.log("Start publishing...");
  client.publish("testTopic", "test");
});

client.on("error", (error) => {
  console.error(error);
});

However, if I connect to the mosquitto broker via mqtt-js cli, it works as expected. E.g. mqtt sub -t 'testTopic' -h 'localhost' and mqtt pub -t 'testTopic' -h 'localhost' -m 'from MQTT.js'.

What am I missing?

3 Answers

your publisher container and broker are running in two different containers that's mean that they are two different machines each machine has it's own ip.

you can't call broker service from your publisher container by using localhost:1883 and vice verse , from broker to publisher container

To reach broker container you have to call container ip or name or service name

in your case change mqtt.connect("mqtt://localhost:1883"); value to be mqtt.connect("mqtt://broker:1883"); and give it a try

The publisher and broker run in different containers, meaning they have different IPs.

When the publisher is trying to reach the broker at localhost:1883, it is normal to receive a ECONNREFUSED, hence the broker is not in the same container.

You should replace the 127.0.0.1 or localhost with the service name of the broker(broker in this case). The service name will be resolved to the correct IP of the broker container.

in your index.js you should change "localhost" to "broker". When inside a container "localhost" will resolve to that specific container so you should always use the service name instead and docker will take care of the routing to that specific service. Also by default all service in the same compose file are added to the same network so there is no need to specify it.

So basically change this: const client = mqtt.connect("mqtt://localhost:1883");

To this: const client = mqtt.connect("mqtt://broker:1883");

Related