This clean separation means that: - you can easily try a new version/feature in Node-RED without affecting the rest of your computer or your existing Node-RED data - you can easily switch to a different version of Node-RED while keeping your data intact
This page assumes docker is already installed, it is available on all platforms. The commandlines shown assume a linux shell (e.g. bash) but they work with minor modifications, e.g. to paths, on other platforms as well. (Pull requests with Windows/Mac examples welcome!)
The following steps bring up a Node-RED instance with FlexDash installed. You can then import one of the built-in examples to explore FlexDash.
Run the following command in your preferred shell (you can use the
\ at the end of every line
or concatenate everything into one long commandline):
docker run --rm -ti -p 1990:1880 \ --entrypoint bash \ --name my-node-red \ nodered/node-red:3.0.1 \ -c "npm i @flexdash/node-red-fd-corewidgets; npm start --cache /data/.npm -- -v -userDir /data"
Open http://localhost:1990/ and you will see the Node-RED editor.
In the commandline window where you launched docker you will see the Node-RED log.
Once you are done, hit ctrl-C for the docker command and everything will vanish.
The commandline above launches a docker container that first installs FlexDash and then runs Node-RED. In more detail, the command options do the following:
-rmdeletes the container after it stops
-tikeeps the container running in the foreground so you can see the Node-RED log and you can hit Ctrl-C to terminate.
-p 1990:1880maps the host's TCP port 1990 to the container's port 1880, which is the port on which Node-RED starts its web server. You can map 1880 to 1880 (
-p 1880:1880), the example above uses a different port in order not to conflict with a regular Node-RED you may already have running. As you might guess, you can run multiple Node-RED containers simultaneously to try out different things as long as you choose a different port and a different container name for each one.
--entrypoint bashruns a shell instead of directly launching Node-RED, which is what the Node-RED image does by default
-name my-node-redgives the container a name which is helpful if you look at running containers (
docker ps) or you want a shell in the container (
docker exec -ti my-node-red bash)
nodered/node-red:3.0.1is the image to download and run, pick a more recent version of Node-RED if there is one.
-c ...is the command the shell is to execute,
npm i @flexdash/node-red-fd-corewidgetsinstalls the core widgets and brings node-red-flexdash in as a dependency, and
npm start ...starts Node-RED
This method of launching Node-RED is great for quickly trying something out from a clean slate. It takes a few seconds to start up and everything is gone at the end.
Test running this on rPi
Keeping data and avoiding the reinstall
The above command launches a truly throw-away container: once it terminates there's nothing left. For a more persistent set-up where you can relaunch the container yet keep your flows and other data, such as file-based context stores, you need to provide a "data" directory to store all this independently of whether a container is running or not. Conveniently, the FlexDash modules can be installed in the data directory so they are persisted too and don't need to be reinstalled every time the container is launched.
Background on Node-RED directories
Before laying out a solution it's worth understanding what can go where and how, because once that's understood the action plan becomes trivial and it becomes easy to tweak things slightly for different purposes.
Node-RED primarily uses two directories: its home directory (or working directory) and
its data directory. When running under docker these are
Node-RED itself is installed in the home dir, which may be read-only,
and it places all user data in
/data, which is assumed to be writable.
Node.js, the programming framework used by Node-RED, expects code to be installed in a
node_modules subdirectory. For example, Node-RED is actually found within
/usr/src/node-red/node_modules. Because Node-RED assumes that its home dir may be read-only
and it needs to be able to install additional packages it uses two
directories: the one in its home directory and also
Finally, to install a package, change directory to the one above
npm install <package>.
We want our data to persist, so we mount a host directory onto
/data, this way when something gets
written there it really is in that host directory.
We also want the packages we install to persist, so we install them into
We then want to repeatedly launch the Node-RED container using the persisted data and persisted
To achieve this two different container runs will be necessary. The first one will install
the desired packages and subsequent runs will just run Node-RED.
For the first run, create a data directory to store the persistent data,
./node-red-data. Then launch a container as follows:
docker run --rm -ti \ -v $PWD/node-red-data:/data \ --entrypoint bash \ nodered/node-red:3.0.1 \ -c "cd /data; npm i @flexdash/node-red-fd-corewidgets"
The only new options compared to the incantation at the top of this page is the -v:
-v $PWD/node-red-data:/datamounts the node-red-data subdirectory onto
/datawithin the container, i.e., any access to files under
/datain the container will be rerouted to
node-red-dataon the host. The paths must be absolute, so under unix
$PWDwill expand to the current working directory. You can also just type out
/home/me/somedir/node-red-dataor under Windows
C:\Users\me\node-red-data(the part after the colon remains
/datasince that's the path inside the container).
This container will run for a few seconds and then exit. You will see the NPM install progress and also spit out some warnings, in particular "saveError ENOENT: no such file or directory, open '/data/package.json'". These warnings are due to the fact that we're installing into an empty directory, which is a bit of an odd usage.
What this accomplishes is to install the chosen packages (here node-red-fd-corewidgets and its dependencies) using the version of npm installed in the container, which is the one Node-RED will also use.
Now comes the second step, which is to actually launch Node-RED:
docker run --rm -ti -p 1990:1880 \ -v $PWD/node-red-data:/data \ --name flexdash-demo \ nodered/node-red:3.0.1
This second incantation is quite simple: it just mounts the persisted data directory onto
/data and starts Node-RED the standard way (plus gives the container a name so a
docker ls shows something recognizable).
- To stop the container, hit Ctrl-C. It can be restarted anytime in the same manner.
- To install additional packages, stop the Node-RED container, run the first incatation with a modified npm commandline, then start the Node-RED container again.
- To try a different version of Node-RED, just alter the
3.0.1part and as long as the versions are compatible, it should work.
- To start from scratch, delete the
node-red-datadirectory and start over.
Installing packages using the palette-manager
Node-RED includes the ability to install packages from its web interface,
specifically using the palette manager found in the top-right menu.
The install tab allows to search for packages and a small install button installs
them in the
data directory just like the
npm install command used above.
In principle, this means that the first docker run above could be skipped, going straight to the
second one, and then simply using the palette manager to install
Unfortunately, as of version 3.0.1 there is a bug, which is that the nodes found in
dependencies are not installed. What this means is that if one installs
are also installed, but the configuration nodes these two packages contain are not loaded
resulting in a non-functional situation.
There are two work-arounds: 1. Explicitly install the dependencies: search for flexdash in the install tab and install all three packages listed above. 2. Install just the corewidgets package, then stop the container and restart it: Node-RED will then pick-up the config nodes from the dependencies.
Using source directories
There is one more tweak that is helpful when developing a new package, e.g. some new FlexDash widgets.
In that case one needs Node-RED to use the package being developed from its source directory
on the host.
The assumed directory layout here is a
node-red-data subdirectory for
/data and a
node-red-fd-mywidgets subdirectory with the new nodes and widgets.
The first incantation to install the source package is very similar to the one above.
The two twists are to map the source directory into the container (previously the packages
came from the internet) and to perform a "link install", which creates a symbolic link in
node_modules to the source directory (within the container, can't link to something outside).
docker run --rm -ti \ -v $PWD/node-red-data:/data \ -v $PWD/node-red-fd-mywidgets:/data/node-red-fd-mywidgets \ --entrypoint bash \ nodered/node-red:3.0.1 \ -c "cd /data; npm i ./node-red-fd-mywidgets"
On the host, looking at
node-red-data/node_modules should show a symbolic link
../node-red-fd-mywidgets. (If the
packages.json has a
name entry with a namespace then it will be a bit different. I named my
@tve/node-red-fd-mywidgets and thus ended up with
node-red-fd-mywidgets needs to have its dependencies right,
specifically, it needs to depend on
node-red-flexdash so the latter gets installed
After this set-up (which could map multiple source package directories, btw) the Node-RED launch is a matter of mounting the appropriate source directories (and the data dir):
docker run --rm -ti -p 1990:1880 \ -v $PWD/node-red-data:/data \ -v $PWD/node-red-fd-mywidgets:/data/node-red-fd-mywidgets \ --name flexdash-demo \ nodered/node-red:3.0.1
When Node-RED is launched there is no npm install happening. Everything works assuming
no dependencies have changed because of the symbolic link. If the dependencies in the
package.json are altered, then a re-run of the first incatation with
npm i is required.
In the end, what the docker containers provide are: - a pre-packaged self-contained installation of Node-RED - an isolated filesystem namespace (directory tree) so arbitrary files on the host cannot be affected - a controlled way to map host directories into the container's namespace
all the docker incantations described on this page basically map host directories into the
container filesystem tree, run some
npm install to install desired packages, and
then run Node-RED.
Hopefully the explanations allow you to customize and tweak docker to suit your needs!
I tried to combine the npm install in /data with launching Node-RED and it didn't work
The command tried is:
docker run --rm -ti -p 1990:1880 \ -v C:\temp\fd_nr_data:/data \ -v C:\Users\Me\node-red-fd-test:/data/node-red-fd-test \ --entrypoint bash \ --name my-node-red \ nodered/node-red:3.0.1 \ -c "cd /data; npm i ./node-red-fd-test; npm start --cache /data/.npm -- -v -userDir /data"
Which produced this output:
[...] + ./firstname.lastname@example.org added 105 packages from 129 contributors and audited 105 packages in 9.408s [...] npm ERR! enoent ENOENT: no such file or directory, open '/data/package.json'
You can see that the npm install worked 'cause npm prints "updated 1 package".
-c commandline first performs
cd /data, then
npm install, and then tries to start
Node-RED using an npm command. The latter looks up what "start" means in
package.json, which isn't
/data, and that produces an error.
package.json to start node-red is in
/usr/src/node-red so one has to
npm start there
(it's the "working directory" of the container, so the bash shell starts there, that's why it works
if there is no cd command).
It is suggested to keep the install and the running separated in two container invocations. To join them one has to cd back before the npm start.