James Thomas

Notes on JavaScript

Node-RED Docker Images

This week, I’ve been helping create and publish official Docker images for the Node-RED project. Users can start Node-RED instances from these images using the following command.

1
docker run -it -p 1880:1880 nodered/node-red-docker

Node-RED is now publishing the following images to Docker Hub for each new release.

When a new version is released on NPM, an automated CI service will build, test and publish new images with the updated version tags.

The source repository for the Docker images is available at https://github.com/node-red/node-red-docker.

Background

There was a long-standing issue open with the project to provide official Docker images for the tool. Many users had already been experimenting with Node-RED and Docker.

Reviewing the community’s efforts, we wanted to create official images that made it simple for users to start Node-RED as Docker containers with minimal configuration whilst allowing for easy customisation, i.e. adding new nodes.

Docker images are created using a configuration file (Dockerfile) that lists the commands to build that image and can start by using another image as the ‘base’.

Node-RED is a Node.js application, published as an NPM module. The Node.js project publishes official Docker images which we used as our base image. These images provide an environment with the correct versions of Node.js and NPM installed.

Rather than manually copying the Node-RED source code into the container image, we used NPM to install the source code by defining a custom package.json which includes Node-RED as dependency.

package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
    "name": "node-red-docker",
    "version": "0.14.5",
    "description": "Docker images for Node-RED",
    "main": "node_modules/node-red/red/red.js",
    "scripts": {
        "start": "node-red"
    },
    ...
    "dependencies": {
        "node-red": "0.14.5"
    },
    "engines": {
        "node": "4.*.*"
    }
}

Adding this file into the container image and then running NPM install, using the ADD and RUN commands, will retrieve the correct Node-RED version and build that into the container image.

Docker images define a default start command to run when the container is created. Using npm start for this image will parse the start script listed in the package.json file, which has been set to node-red.

Adding New Nodes

Node-RED has a huge community which produces custom nodes for everything from accessing data from a Raspberry Pi’s sensors to a Tesla car.

Additional nodes can be installed by putting the files into your user directory, which defaults to $HOME/.node-red.

Allowing users to install additional nodes without building new images is possible using Docker’s volume support. Docker data volumes can be used to share files between the container and the host system, by mounting a directory on the host as a data volume within the container.

Exposing the Node-RED user directory within the container as a data volume means users can mount this on the host system. Nodes installed into this directory, using NPM on the host system, will automatically be registered when Node-RED starts.

Within the Dockerfile for the Node-RED image, the /data directory is configured as the user directory and exported as a data volume.

Users can mount their local user directory into the container with the following command.

1
docker run -it -p 1880:1880 -v ~/.node-red:/data nodered/node-red-docker

Environment Parameters

Docker supports injecting environment parameter values into running containers, using command-line options on the host system. This is often used to configure runtime options without users having to build new container images. Node-RED’s Docker images support the following environment parameters.

Flows Configuration

User flow configurations are stored in a JSON file under the user directory. This defaults to flows.json but can be configured using an environment parameter (FLOWS) passed to the container, as shown below.

1
docker run -it -p 1880:1880 -e FLOWS=my_flows.json nodered/node-red-docker

Node Options

Node.js runtime arguments can be passed to the container using an environment parameter (NODE_OPTIONS). For example, to fix the heap size used by the Node.js garbage collector you would use the following command.

1
docker run -it -p 1880:1880 -e NODE_OPTIONS="--max_old_space_size=128" nodered/node-red-docker

Alpine Linux Image

The official Node.js Docker image uses the Debian Jessie base image. This image provides a full Linux install, which means dependent Docker images can be hundreds of megabytes in size. Node-RED’s Docker image, using this base image, is nearly 300 MB.

Reducing Docker image sizes can dramatically reduce build and deployment times.

Alpine Linux is a lightweight Linux distribution, focused on security and performance. A minimal Docker image based on Alpine Linux is only 5 MB in size!

Using the alpine-node base image, which provides an Alpine Linux environment with Node.js & NPM, in our Dockerfiles reduces the resulting image file to under 50 MB.

Alpine Linux does make it more difficult to install NPM modules with native dependencies, due to missing common libraries and tools needed to build them.

Therefore, we’re publishing the Alpine Linux image as a seperate tag (slim), rather than using this base image throughout our Dockerfiles.

This version should provide an extremely lightweight Node-RED image that works for most users.

1
docker run -it -p 1880:1880 nodered/node-red-docker:slim

Raspberry Pi Image

Node-RED is an incredibly popular tool for hacking on the Raspberry Pi. Using a custom Raspberry Pi image, developers can also have a full Docker system running in the Linux environment on their device.

So, can we use Docker to start Node-RED on the Raspberry Pi?

Due to the platform architecture, ARM rather than x86/x64 by Intel or AMD, Docker images must be packaged specifically for that platform. The existing Docker images created for Node-RED will not work.

Fortunately, there’s an existing RPi-compatible Docker image with Node.js and NPM.

Using this base image to build a new Raspberry Pi-specific Node-RED image, published with the rpi tag, means users can now start Node-RED on the Raspberry Pi using Docker.

1
docker run -it -p 1880:1880 nodered/node-red-docker:rpi

Comments