Skip to Content
Technical Articles
Author's profile photo Radu Constantin Simen

How To Deploy a Public MQTT Server in Cloud Foundry using a Docker Image

0. Pre-requirements

1. Introduction about MQTT and SAP Cloud Platform

When you are working on an IoT scenario most of the time you have to use an MQTT server.

When the solution needs to be hosted in cloud then your options are limited because most of them are paid services or public servers that anybody can use an publish data.

Within the SAP Cloud Platform you can find RabbitMQ in the Service Marketplace.

It’s a great service but it may be binded to your Cloud Foundry apps and it can’t be exposed as a public service on the internet.

There is an workaround for this limitation of the environment : In Cloud Foundry anyone can deploy Docker Images with a simple bash command.

Working with Node.JS I know that everything may be found on www.npmjs.com. There you can find a standalone MQTT server named mosca.

More details about this subject can be found in this article

To be able to use a MQTT Server for non-critical data you can apply the following scenario

  • create a custom Docker image based on a Linux OS that runs mosca
  • test it with a MQTT client that support WSS (Web Sockets Secure) – see publisher.js file below
  • check the messages with the same client – see subscriber.jsfile below

I used in this example MQTT.js package for Node.JS.

 

2. How to create and build a new Docker Image

2.1 Create a file named Dockerfile and copy/paste/adapt the code below

You can pull the existing Docker Image from here

Dockerfile content for copy/paste :

FROM ubuntu:18.04
MAINTAINER Radu Simen <radu103@hotmail.com>
RUN ln -fs /usr/share/zoneinfo/Europe/Bucharest /etc/localtime
RUN apt-get update
RUN apt-get install -y nodejs npm
RUN apt-get install -y make gcc g++ python git gyp build-essential
RUN npm install -g npm@latest
RUN node -v
RUN npm -v
RUN npm install -g node-gyp@latest
RUN chmod -R 777 /root
RUN chmod -R 777 /usr/local/lib
RUN npm install -g mosca bunyan
EXPOSE 80
ENTRYPOINT ["mosca", "--http-port", "80", "--http-bundle", "-v"]

 

2.2 Build and publish the image to the docker hub webpage

Open a new terminal window and navigate to the folder where you saved the Dockerfile and run :

docker login

docker build ./ -t radu103/mosca:latest -t radu103/mosca:1.0.0`
docker push radu103/mosca:1.0.0
docker push radu103/mosca:latest

 

2.3 Check the image and run a Docker Container

docker run radu103/mosca:latest
docker ps

You can use also Kitematic UI to see containers and images.

 

3. Deploy the Docker Image on SAP Cloud Platform

cf login
cf push <APP_NAME> -m 256M --docker-image radu103/mosca:latest

 

4. Test the SAP Cloud Platform new deployed app

Run in terminal to see <APP_NAME> logs

cf logs <APP_NAME> --recent

Open a browser and check https://<APP_URL>/mqtt.js (because mosca is started with –http-bundle flag)

 

5. Publish and Consume Messages Example with a Node.JS app

5.1 Create a new folder with the folowing files

  1. File package.json
{
  "name": "stm-mqtt-broker",
  "version": "1.0.0",
  "description": "",
  "main": "publisher.js",
  "engines": {
    "node": "^8.1.3",
    "npm": "^6.1.0"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "mqtt": "^2.18.3"
  }
}

2. File publisher.js

var mqtt = require('mqtt');

var mqttHost = 'wss://<APP_NAME>.cfapps.eu10.hana.ondemand.com:443';
var topicName = 'myTopic';

var client  = mqtt.connect(mqttHost);

client.on('connect', function () {
    setInterval(function() {
        var date = new Date();
        var message = 'Hello mqtt ' + date.getTime();
        client.publish(topicName, message);

        date = new Date();
        console.log(date.getTime() + ' - Message Sent : ' + message);
    }, 5000);
});

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

3. File subscriber.js

var mqtt = require('mqtt');

var mqttHost = 'wss://<APP_NAME>.cfapps.eu10.hana.ondemand.com:443';
var topicName = 'myTopic';

var client  = mqtt.connect(mqttHost);

client.on('connect', function () {
    client.subscribe(topicName);
});

client.on('message', function (topic, message) {
    
    context = topic + " : "  + message.toString();

    var date = new Date();

    console.log(date.getTime() + " - " + context);
});

5.2 Run Publisher app and Subscriber app in terminal

npm install
node publisher.js
node subscriber.js

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo kepa santos
      kepa santos
      Hi,thank you very much for the tutorial, It has helped me a lot, but I have a doubt, it is possible to send messages through "mqtt://" protocol?

       

      Author's profile photo Radu Constantin Simen
      Radu Constantin Simen
      Blog Post Author

      the example was tested and used last summer by a colleague, so it should work

      Author's profile photo Gabriel Catalin Pirvu
      Gabriel Catalin Pirvu

      I can confirm that I tested it and it worked.

      Author's profile photo Witalij Rudnicki
      Witalij Rudnicki

      Hi Radu. Thanks for openning my eyes to so many new possibilities with this post 🙂 I've been playing with this for last two days forgetting about other stuff I need to do...

      One quite remark: in package.json you do not need mosca dependency - this makes npm i faster and cleaner.

      "mosca": "^2.8.3"

      Well done!

      Author's profile photo Radu Constantin Simen
      Radu Constantin Simen
      Blog Post Author

      You're right so I removed it

      Author's profile photo Kevin Hunter
      Kevin Hunter

      Hi Radu,

      Great blog, Ive looking for this functionality for a while.

      Thanks

      Kevin