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.
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.
- latest - uses official Node.JS v4 base image.
- slim - uses Alpine Linux base image.
- rpi - uses RPi-compatible base image.
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.
{
"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.
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.
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.
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.
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.
docker run -it -p 1880:1880 nodered/node-red-docker:rpi