Dockerize Javascript IOT Applications

Written by Ulises Gascón

Jul 03, 20236 min read
I am eating my breakfast while doing IOT Development in a Coffee Shop

I am a Docker Captain and I love build Robots and IoT devices.

In those years I have been doing a lot of IoT prototypes for companies and for myself. I have been using Arduino, Raspberry Pi, and other microcontrollers.

There are few things that make IoT development very different from other types of software development. One of them is that you need to have a physical device to test your code or build a good simulator. This means that you need to have a device that you can connect to your computer and run your code on it.

It was very common for me to have a lot of devices, sensors and wires in my backpack while commuting to work. I end up having many funny situations when I was doing IoT development in Coffee Shops around the world, just like the picture above and many others from 2015.

Introduction

When Arduino started to become popular, I was very excited about the idea of building my own IoT devices. I started to learn how to program in C/C++ and I bought a lot of sensors and other components to build my own projects.

But I soon realized that I was spending too much time on the Arduino source code, so I decided to use Javascript instead. I started to use Johnny-Five and I was able to build complex IoT device in a few hours.

Prototype is the new MVP

Very simple IOT device with a RGB light controlled with JS in a candy jar

While the JSDayES 2016 was taking place, I was in one of the stands. During the breaks I was able to hack the welcome candy jar and build a simple IoT device that was controlled by a Node.js server. The device was able to change the color of the light depending on the logic that you define in a simple Node.js App.

Why Johnny Five is so cool?

Johnny Five Banner

The library Johnny-Five is a Javascript library that allows you to control Arduino and other microcontrollers using Javascript. It is very easy to use and it has a lot of examples that you can use to learn how to use it.

As a Javascript developer, I was very happy to be able to use the same language to build IoT devices:

The typical blink led example for an Arduino board looks like this:

var five = require("johnny-five");
var board = new five.Board();

board.on("ready", function() {
  var led = new five.Led(13);
  led.blink(1000);
});

In compare to the classic approach:

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);                      // wait for a second
}

It might not look like a big difference, but when you are building complex IoT devices, it makes a big difference. You can use all the Javascript features like Promises, Async/Await, etc. to build your IoT devices and all the compute power that the host device provides, as well all the modern communication that we expect today (HTTP APIS, SDKs..).

This will force you to connect (USB, Bluetooth...) the IoT device to a computer all the time as the device won't have the instructions recorded.

Obviously not all the IOT projects fits this requirements, but for a simple prototype is a fantastic solution.

Why should I Dockerize my project?

Johnny Five is a fantastic library, but some of their dependencies have a complex installation process (under the hood), this sometimes makes difficult to install the library in some environments. Specially if you need to change between devices, it was very frustrating for me at the beginning until I decided to use Docker to make it easier to execute.

Dockerize your JS IoT application

I created this repository to dockerize the blink example, so it is easier to follow and explore the details.

Get the necessary software

Before you begin, you need to have Docker installed on your machine.

Write a Dockerfile

Here is a hyper simplified Dockerfile, if you want to build a production ready example Start from this

If you speak Spanish I also recommend you my ebook "Docker Seguro"

FROM node:18.14.1
WORKDIR /usr/src/app
RUN apt-get update
RUN apt-get -y install udev
COPY package*.json ./
RUN npm install --unsafe-perm --build-from-source=serialport
COPY . .
CMD [ "npm", "run", "start" ]

Build the Docker image

Using the docker build command, create a Docker image.

docker build -t blink .

Run your application in a Docker container

Launch your application using the docker run command, specifying the necessary parameters to configure your container.

Here is the tricky part, you will need to pass the USB device to the container, so it can access the Arduino board.

docker run -it --rm --privileged --device=/dev/ttyUSB0 blink

In my case the port was /dev/ttyUSB0, but this might be different for you. In this Guide you can find more information.

Sometimes access to USB devices from Docker can be tricky, especially in macOS.

Can I pass through a USB device to a container? Unfortunately, it is not possible to pass through a USB device (or a serial port) to a container as it requires support at the hypervisor level. Docker: General FAQs for Desktop

But there are many workarounds from the community:

Publish your Docker image

Optionally, you can publish your Docker image to a container registry, such as Docker Hub, for easy access and distribution.