0
votes

I am running Eclipse Mosquitto on a local docker container on 172.17.0.2:1883

I am able to publish/subscribe using MQTT.fx client but now trying to connect to the broker from node and haven't been able to.

The topic is "sensors"

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES
e747c86b6ec1        eclipse-mosquitto   "/docker-entrypoint.…"   5 hours ago         Up 5 hours          0.0.0.0:1883->1883/tcp, 0.0.0.0:9001->9001/tcp   adoring_varahamihira

When I inspect the IP address

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' e747c86b6ec1
172.17.0.2

I am trying to use the following node server to connect to my MQTT broker but the 'connect' event never seems to happen.

// Note: I have an express server running but didn't include 
const mqtt = require("mqtt")

var MQTT_TOPIC = "sensors";
var MQTT_ADDR = "mqtt://172.17.0.2";
var MQTT_PORT = 1883;

var client = mqtt.connect(MQTT_ADDR, {
  port: MQTT_PORT,
  clientId: 'bgtestnodejs232323',
  protocolId: 'MQIsdp',
  protocolVersion: 3,
  connectTimeout: 1000,
  debug: true
});

client.on('connect', function () {
  console.log("connected!")
});

client.on('error', function (err) {
  console.log(err)``
  client.end()
})

When I run:

console.log(util.inspect(client))

The output is:

MqttClient {
  options:
   { protocol: 'mqtt',
     slashes: true,
     auth: null,
     host: '172.17.0.2',
     port: 1883,
     hostname: '172.17.0.2',
     hash: null,
     search: null,
     query: [Object: null prototype] {},
     pathname: null,
     path: null,
     href: 'mqtt://172.17.0.2',
     clientId: 'bgtestnodejs232323',
     protocolId: 'MQIsdp',
     protocolVersion: 3,
     connectTimeout: 1000,
     debug: true,
     defaultProtocol: 'mqtt',
     keepalive: 60,
     reschedulePings: true,
     reconnectPeriod: 1000,
     clean: true,
     resubscribe: true,
     customHandleAcks: [Function] },
  streamBuilder: [Function: wrapper],
  outgoingStore: Store { options: { clean: true }, _inflights: Map {} },
  incomingStore: Store { options: { clean: true }, _inflights: Map {} },
  queueQoSZero: true,
  _resubscribeTopics: {},
  messageIdToTopic: {},
  pingTimer: null,
  connected: false,
  disconnecting: false,
  queue: [],
  connackTimer:
   Timeout {
     _called: false,
     _idleTimeout: 1000,
     _idlePrev: [TimersList],
     _idleNext: [TimersList],
     _idleStart: 478,
     _onTimeout: [Function],
     _timerArgs: undefined,
     _repeat: null,
     _destroyed: false,
     [Symbol(unrefed)]: false,
     [Symbol(asyncId)]: 9,
     [Symbol(triggerId)]: 1 },
  reconnectTimer: null,
  _storeProcessing: false,
  _packetIdsDuringStoreProcessing: {},
  nextId: 26898,
  outgoing: {},
  _firstConnection: true,
  _events:
   [Object: null prototype] {
     close: [ [Function], [Function], [Function] ],
     connect: [Function] },
  _eventsCount: 2,
  _maxListeners: undefined,
  stream:
   Socket {
     connecting: true,
     _hadError: false,
     _handle:
      TCP {
        reading: false,
        onread: [Function: onStreamRead],
        onconnection: null,
        [Symbol(owner)]: [Circular] },
     _parent: null,
     _host: null,
     _readableState:
      ReadableState {
        objectMode: false,
        highWaterMark: 16384,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: [Writable],
        pipesCount: 1,
        flowing: true,
        ended: false,
        endEmitted: false,
        reading: false,
        sync: true,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: true,
        paused: false,
        emitClose: false,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: false,
        decoder: null,
        encoding: null },
     readable: false,
     _events:
      [Object: null prototype] {
        end: [Array],
        data: [Function: ondata],
        error: [Function: nop],
        close: [Function] },
     _eventsCount: 4,
     _maxListeners: 1000,
     _writableState:
      WritableState {
        objectMode: false,
        highWaterMark: 16384,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: false,
        defaultEncoding: 'utf8',
        length: 34,
        writing: false,
        corked: 1,
        sync: true,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: [Object],
        lastBufferedRequest: [Object],
        pendingcb: 9,
        prefinished: false,
        errorEmitted: false,
        emitClose: false,
        bufferedRequestCount: 9,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: false,
     _sockname: null,
     _pendingData: null,
     _pendingEncoding: '',
     server: null,
     _server: null,
     [Symbol(asyncId)]: 5,
     [Symbol(lastWriteQueueSize)]: 0,
     [Symbol(timeout)]: null,
     [Symbol(kBytesRead)]: 0,
     [Symbol(kBytesWritten)]: 0 } }

I have been trying the suggestions in this answer: Why is MQTT not connecting with NodeJS?

Thanks for your help!

2
noticed that you run the broker on 1883, but then again I see that you use 9001 in your code. Is the 9001 the right port? - idan
Apologies this was my mistake - I was experimenting with 9001. It doesn't work with 9001 or 1883. I will edit the question to be 1883 and appropriate output. - jackbridger
Where is the nodejs code running (docker host, or in another container on the same host)? Also add a client.on('error', function(err){}) callback so you can see why the client is not connecting. - hardillb
Nodejs code is running on localhost. I do have the error handler in my code but it doesn't trigger (I edited it in above). Thanks again - jackbridger
By localhost you mean the machine that is hosting the docker engine? - hardillb

2 Answers

3
votes

The IP address range 172.17.0.0/16 that is handed out to Docker containers by the Docker engine are part of the RFC1918 set intended for private use.

In the case of Docker, they are used on the internal "bridge" network and only accessible from other docker containers or the machine hosting the Docker engine.

The 0.0.0.0:1883->1883/tcp, 0.0.0.0:9001->9001/tcp output for the info of your mosquitto container shows that these ports have been exposed and are mapped to the host machines IP address. You should be able to connect if you change 172.17.0.2 for the IP address of the machine hosting the Docker engine.

2
votes
  • Port 9001 is the websocket listener
  • Port 1883 is the native MQTT listener

You are using the mqtt:// schema for your broker URL which indicates the native MQTT protocol, yet you are forcing the use of port 9001.

If you want to use WebSockets then you should change the schema to ws://

If you want to use native MQTT then you need to change the port to 1883