You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -45,9 +45,9 @@ Periodically, the source code is recompiled and pushed to [nodered/node-red](htt
45
45
46
46
### IOTstack menu { #iotstackMenu }
47
47
48
-
When you select Node-RED in the IOTstack menu, the *template service definition* is copied into the *Compose* file.
48
+
When you select Node-RED in the IOTstack menu, the *template service definition*❶ is copied into the *Compose* file ❹.
49
49
50
-
> Under old menu, it is also copied to the *working service definition* and then not really used.
50
+
> Under old menu, it is also copied to the *working service definition*❸ and then not really used.
51
51
52
52
You choose add-on nodes from a supplementary menu. We recommend accepting the default nodes, and adding others that you think you are likely to need. Node-RED will not build if you do not select at least one add-on node.
53
53
@@ -56,7 +56,7 @@ Key points:
56
56
* Under new menu, you must press the right arrow to access the supplementary menu. Under old menu, the list of add-on nodes is displayed automatically.
57
57
* Do not be concerned if you can't find an add-on node you need in the list. You can also add nodes via Manage Palette once Node-RED is running. See [component management](#componentManagement).
58
58
59
-
Choosing add-on nodes in the menu causes the *Dockerfile* to be created.
59
+
Choosing add-on nodes in the menu causes the *Dockerfile*❷ to be created.
60
60
61
61
### IOTstack first run { #iotstackFirstRun }
62
62
@@ -67,7 +67,7 @@ $ cd ~/IOTstack
67
67
$ docker-compose up -d
68
68
```
69
69
70
-
`docker-compose` reads the *Compose* file. When it arrives at the `nodered` service definition, it finds:
70
+
`docker-compose` reads the *Compose* file ❹. When it arrives at the `nodered` service definition, it finds <aname="serviceBuildFragment"><a>:
71
71
72
72
```yaml linenums="1"
73
73
nodered:
@@ -87,11 +87,11 @@ Note:
87
87
build: ./services/nodered/.
88
88
```
89
89
90
-
The older syntax meant all local customisations (version-pinning and adding extra packages) needed manual edits to the *Dockerfile*. Those edits would be overwritten each time the menu was re-run to alter the selected add-on nodes. The newer multi-line syntax avoids that problem.
90
+
The older syntax meant all local customisations (version-pinning and adding extra packages) needed manual edits to the *Dockerfile* ❷. Those edits would be overwritten each time the menu was re-run to alter the selected add-on nodes. The newer multi-line syntax avoids that problem.
91
91
92
92
See also [updating to July 2022 syntax](#july2022syntax).
93
93
94
-
In either case, the path `./services/nodered/.` tells `docker-compose` to look for:
94
+
In either case, the path `./services/nodered/.` tells `docker-compose` to look for ❷:
95
95
96
96
```
97
97
~/IOTstack/services/nodered/Dockerfile
@@ -106,25 +106,25 @@ Notes:
106
106
107
107
> Acknowledgement: Successful installation of the SQLite node is thanks to @fragolinux.
108
108
109
-
When you run the `docker images` command after Node-RED has been built, you *may* see two rows for Node-RED:
109
+
When you run the `docker images` command after Node-RED has been built, you will see something like this:
110
110
111
111
``` console
112
112
$ docker images
113
-
REPOSITORY TAG IMAGE ID CREATED SIZE
114
-
iotstack_nodered latest b0b21a97b8bb 4 days ago 462MB
115
-
nodered/node-red latest deb99584fa75 5 days ago 385MB
113
+
REPOSITORY TAG IMAGE ID CREATED SIZE
114
+
iotstack-nodered latest 9feeb87019cd 11 days ago 945MB
116
115
```
117
116
118
-
* `nodered/node-red` is the *base image*; and
119
-
* `iotstack_nodered` is the *local image*. The *local* image is the one that is instantiated to become the running container.
117
+
The image name `iotstack-nodered` is the concatenation of two components:
120
118
121
-
You *may* see the same pattern in Portainer, which reports the *base image* as "unused":
119
+
1. The `docker-compose` *project* name. This is the all-lower-case representation of the name of the folder containing `docker-compose.yml`. In a default clone of IOTstack, the folder name is `IOTstack` so the project name is `iotstack`.
120
+
2. The name of the service definition which, for Node-RED is `nodered`.
When you install Node-RED for the first time, the entire process of downloading a *base* image from Dockerhub, building a *local* image by running your local Dockerfile ❷, and then instantiating that *local* image as your running container, is all completely automatic.
124
123
125
-
You should not remove the *base* image, even though it appears to be unused.
124
+
However, *after* that first build, your *local* image is essentially frozen and it needs special action on your part to keep it up-to-date. See [maintaining Node-RED](#maintainNodeRed) and, in particular:
126
125
127
-
> Whether you see one or two rows depends on the version of Docker you are using and how your version of `docker-compose` builds local images.
126
+
* [Re-building the local image](#rebuildNodeRed) if you change the Dockerfile; and
127
+
* [Upgrading Node-RED](#upgradeNodeRed) if you want to reconstruct your *local* image based on an updated *base* image which has become available on [DockerHub](https://hub.docker.com/r/nodered/node-red/tags).
128
128
129
129
## Securing Node-RED { #securingNodeRed }
130
130
@@ -267,9 +267,9 @@ The third method is *portable*, meaning a flow can conceptually refer to "this"
> If `jq` is not installed on your system, you can install it by running `sudo apt install -y jq`.
272
-
272
+
273
273
If you use this method, your flows can refer to "this" host using the IP address "172.17.0.1".
274
274
275
275
* Method 2
@@ -282,7 +282,7 @@ The third method is *portable*, meaning a flow can conceptually refer to "this"
282
282
```
283
283
284
284
If you use this method, your flows can refer to "this" host using the domain name "host.docker.internal".
285
-
285
+
286
286
Generally the second method is recommended for IOTstack. That is because your flows will continue to work even if the 172.17.0.1 IP address changes. However, it does come with the disadvantage that, if you publish a flow containing this domain name, the flow will not work unless the recipient also adds the `extra_hosts` clause.
287
287
288
288
## GPIO Access { #accessGPIO }
@@ -428,12 +428,12 @@ To communicate with your Raspberry Pi's GPIO you need to do the following:
428
428
4. Drag a `pi gpio` node onto the canvas. Configure it according to your needs.
429
429
430
430
The `Host` field should be set to one of:
431
-
431
+
432
432
* `172.17.0.1`; or
433
433
* `host.docker.internal`
434
434
435
435
See also [Bridge network - default gateway](#defaultBridge).
436
-
436
+
437
437
Don't try to use 127.0.0.1 because that is the loopback address of the Node-RED container.
438
438
439
439
## Serial Devices { #accessSerial }
@@ -501,7 +501,7 @@ You have three basic options:
501
501
```
502
502
503
503
In the above:
504
-
504
+
505
505
* "188" is the major number for ttyUSB0 and you should substitute accordingly if your device has a different major number.
506
506
507
507
* the "*" is a wildcard for the minor number.
@@ -546,7 +546,7 @@ Historically, `/dev/ttyAMA0` referred to the Raspberry Pi's serial port. The sit
546
546
```
547
547
548
548
And, if that isn't sufficiently confusing, the location of `config.txt` depends on the OS version:
549
-
549
+
550
550
* Bullseye (and earlier): `/boot/config.txt`
551
551
* Bookworm: `/boot/firmware/config.txt`
552
552
@@ -560,7 +560,7 @@ Rolling all that together, if you want access to the hardware serial port from N
560
560
devices:
561
561
- /dev/serial0:/dev/«internalDevice»
562
562
```
563
-
563
+
564
564
where `«internalDevice»` is whatever device the add-on node you're using is expecting, such as `ttyAMA0`.
565
565
566
566
4. Recreate the Node-RED container by running:
@@ -569,7 +569,7 @@ Rolling all that together, if you want access to the hardware serial port from N
569
569
$ cd ~/IOTstack
570
570
$ docker-compose up -d nodered
571
571
```
572
-
572
+
573
573
### Bluetooth device { #bluetoothSupport }
574
574
575
575
If you enable the `node-red-contrib-generic-ble` add on node, you will also need to make the following changes:
@@ -585,19 +585,19 @@ If you enable the `node-red-contrib-generic-ble` add on node, you will also need
585
585
```
586
586
dtparam=krnbt=off
587
587
```
588
-
588
+
589
589
You then need to reboot. This adds the Bluetooth device to `/dev`.
590
590
591
591
2. Find the the Node-RED service definition in your `docker-compose.yml`:
592
592
593
593
* Add the following mapping to the `volumes:` clause:
* Historically, `/dev/ttyAMA0` meant the serial interface. Subsequently, it came to mean the Bluetooth interface but only where Bluetooth hardware was present, otherwise it still meant the serial interface.
619
619
620
620
On Bookworm and later, if it is present, `/dev/ttyAMA1` means the Bluetooth Interface.
621
-
621
+
622
622
On Bullseye and later, `/dev/serial1` is a symbolic link pointing to whichever of `/dev/ttyAMA0` or `/dev/ttyAMA1` means the Bluetooth interface. This means that `/dev/serial1` is the most reliable way of referring to the Bluetooth Interface. That's why it appears in the `devices:` clause above.
623
623
624
624
## Sharing files between Node-RED and the Raspberry Pi { #fileSharing }
@@ -1104,7 +1104,7 @@ To rebuild your *local* image:
1104
1104
``` console
1105
1105
$ cd ~/IOTstack
1106
1106
$ docker-compose up --build -d nodered
1107
-
$ docker system prune
1107
+
$ docker system prune -f
1108
1108
```
1109
1109
1110
1110
Think of these commands as "re-running the *Dockerfile*". The only time a *base* image will be downloaded from *DockerHub is when a *base* image with a tag matching the value of `DOCKERHUB_TAG` can't be found on your Raspberry Pi.
@@ -1139,7 +1139,7 @@ Once a new version appears on [*DockerHub*](https://hub.docker.com), you can upg
1139
1139
$ cd ~/IOTstack
1140
1140
$ docker-compose build --no-cache --pull nodered
1141
1141
$ docker-compose up -d nodered
1142
-
$ docker system prune
1142
+
$ docker system prune -f
1143
1143
```
1144
1144
1145
1145
Breaking it down into parts:
@@ -1553,3 +1553,161 @@ All remaining lines of your original *Dockerfile* should be left as-is.
1553
1553
### Applying the new syntax { #july2022build }
1554
1554
1555
1555
Run the [re-building the local Node-RED image](#rebuildNodeRed) commands.
1556
+
1557
+
## Alpine vs Debian { #linuxDistro }
1558
+
1559
+
The first part of IOTstack's default service definition for Node-RED is shown at [IOTstack first run](#serviceBuildFragment). Although it is not immediately obvious, this results in a container which is based on the Alpine Linux distribution. You can confirm this by running:
In addition, Node-RED images based on Alpine have offered a greater range of options when it comes to the embedded version of Node.js. At the time of writing:
1579
+
1580
+
* image variants based on Alpine Linux include `latest-18`, `latest-20` and `latest-22`, implying a choice of Node.js versions 18, 20 and 22, with version 20 being the default; while
1581
+
* the single image variant for Debian Linux is `latest-debian` which comes with Node.js version 20.
1582
+
1583
+
Naturally, this situation could change at any time! This information is only here to make the point that, historically, Node-RED images based on Debian have lagged behind Alpine and have only supported a single version of Node.js. This is also the main reason why IOTstack defaults to Alpine images.
1584
+
1585
+
However, there may be circumstances where you decide it is appropriate to run a Node-RED image based on Debian. The purpose of this section is not to explore scenarios nor weigh the pros and cons, merely to explain how to adapt your Node-RED service definition to accomplish it. Proceed as follows:
1586
+
1587
+
1. Make a copy of your existing Dockerfile:
1588
+
1589
+
``` console
1590
+
$ cd ~/IOTstack/services/nodered
1591
+
$ cp Dockerfile Debian.Dockerfile
1592
+
```
1593
+
1594
+
The reason for making a copy is to preserve your existing (Alpine-aware) Dockerfile so you can easily switch back if you break something.
1595
+
1596
+
2. Open `Debian.Dockerfile` in a text editor and make the following changes:
1597
+
1598
+
* Find the line:
1599
+
1600
+
``` Dockerfile linenums="4"
1601
+
ARG DOCKERHUB_TAG=latest
1602
+
```
1603
+
1604
+
**Replace** that line with:
1605
+
1606
+
``` Dockerfile linenums="4"
1607
+
ARG DOCKERHUB_TAG=latest-debian
1608
+
```
1609
+
1610
+
* Find the line:
1611
+
1612
+
``` Dockerfile linenums="15"
1613
+
RUN apk update && apk add --no-cache eudev-dev ${EXTRA_PACKAGES}
1614
+
```
1615
+
1616
+
**Replace** that line with:
1617
+
1618
+
``` Dockerfile linenums="15"
1619
+
RUN apt update && apt install -y udev ${EXTRA_PACKAGES}
1620
+
```
1621
+
1622
+
`apk`is the Alpine package manager whereas `apt` is the Debian package manager.
1623
+
1624
+
* Save your work.
1625
+
1626
+
3. Make a copy of your existing compose file:
1627
+
1628
+
``` console
1629
+
$ cd ~/IOTstack
1630
+
$ cp docker-compose.yml docker-compose.yml.bak
1631
+
```
1632
+
1633
+
The reason for making a copy is to preserve your existing (Alpine-aware) service definition so you can easily switch back if you break something.
1634
+
1635
+
4. Open `docker-compose.yml ` in a text editor and make the following changes:
1636
+
1637
+
* Change the Node-RED `build` clause so that it looks like this:
1638
+
1639
+
``` yaml linenums="3"
1640
+
build:
1641
+
context: ./services/nodered/.
1642
+
dockerfile: Debian.Dockerfile
1643
+
args:
1644
+
- DOCKERHUB_TAG=latest-debian
1645
+
- EXTRA_PACKAGES=
1646
+
```
1647
+
1648
+
There are two key edits:
1649
+
1650
+
1. **Insert** the `dockerfile` line (as line 5).
1651
+
2. **Change** the right hand side of the `DOCKERHUB_TAG` argument from `latest` to `latest-debian` (line 7).
1652
+
1653
+
* If you have any `EXTRA_PACKAGES` specified, you will need to allow for any package-name differences between Alpine and Debian. For example, suppose you are using this list of extra packages with Alpine:
1654
+
1655
+
``` yaml linenums="8"
1656
+
- EXTRA_PACKAGES=mosquitto-clients bind-tools tcpdump tree
1657
+
```
1658
+
1659
+
The `mosquitto-clients`, `tcpdump` and `tree` packages have the same names in the `apk` (Alpine) package manager as they do in `apt` (Debian) whereas `bind-tools` is named `dnsutils` in the Debian repositories. Thus the extra packages list for a Debian build would need to be:
1660
+
1661
+
``` yaml linenums="8"
1662
+
- EXTRA_PACKAGES=mosquitto-clients dnsutils tcpdump tree
1663
+
```
1664
+
1665
+
* Save your work.
1666
+
1667
+
5. Rebuild Node-RED:
1668
+
1669
+
``` console
1670
+
$ cd ~/IOTstack
1671
+
$ docker-compose build --no-cache --pull nodered
1672
+
```
1673
+
1674
+
If the build process reports any errors, go back and check your work.
1675
+
1676
+
6. Start the new container:
1677
+
1678
+
``` console
1679
+
$ docker-compose up -d nodered
1680
+
```
1681
+
1682
+
7. Check that the new container is running properly and hasn't gone into a restart loop:
1683
+
1684
+
``` console
1685
+
$ docker ps -a --format "table {{.Names}}\t{{.RunningFor}}\t{{.Status}}\t{{.Size}}" --filter name=nodered
1686
+
NAMES CREATED STATUS SIZE
1687
+
nodered 32 seconds ago Up 31 seconds (healthy) 0B (virtual 945MB)
1688
+
```
1689
+
1690
+
Providing the STATUS column reports "healthy" after roughly 30 seconds of runtime, it is usually safe to assume that the container is behaving normally.
1691
+
1692
+
8. Verify the base Linux distribution being used by the container:
The actual version numbers you see in the last two steps will depend (obviously) on whatever the good folks who maintain Node-RED thought was appropriate at the time they released whatever `latest-debian` variant is present on DockerHub at the moment when you perform the migration.
1712
+
1713
+
Please keep in mind that none of this affects the IOTstack menu. Re-running the menu is likely to revert your Node-RED service definition to be based on Alpine images.
0 commit comments