Communication between NR dockerized and the host where it run
I worked a lot on NR in docker and I want to share my research and implementation.
Indeed how to pass orders between these 2 environments (Host & Guest docker) which are supposed to be watertight one towards the other apart from the directory sharing.
Concrete use case :
How to restart the Pi or NR container in a planned or unplanned way from a NR flow ?
Where it used to be enough to use an EXEC node with the sudo reboot command or node-red-restart on standard installation, in a container this does not work anymore.
You have to pass the reboot order to the host or the docker command to restart a container
So you have to tell the host to run the right commands.
1) Get the IP address of the host.
The main thing is to get the IP address of the host at startup and to pass it to the container via a shared host/container file. This will be read by NR docker when it starts.
Example:
This script get-ip4.sh retrieves the IP address of the P
#!/bin/bash
(/sbin/ip -o -4 addr list wlan0 | awk '{print $4}' | cut -d/ -f1) > global-variables/ip4.txt
Put the script at the boot of the Pi !
crontab -e
@reboot sleep 08 && /home/pi/get-ip4.sh
2) Webhook: The solution I used to place orders
Next, I opted for the Webhook solution.
See here: GitHub - adnanh/webhook: webhook is a lightweight incoming webhook server to run shell commands
sudo apt-get install webhook
In short, on the host, a daemon listens on a specific URL for an order to be given to it and then executes a script that for example restarts the Pi or checks if the OLED screen is on or off or restart a container.
Example of the hooks.json file
[
{
"id": "oled-status",
"execute-command": "/home/pi/oled-status.sh",
"command-working-directory": "/home/pi/tmp"
},
{
"id": "reboot",
"execute-command": "/home/pi/reboot.sh",
"command-working-directory": "/home/pi/tmp"
}
]
2.1 - Create a service that will listen on a defined port (ex:8999) the given order
sudo nano /etc/systemd/system/webhook.service
[Unit]
Description=System Starting Webhook for NodeRed
[Service]
ExecStart=webhook -hooks /home/pi/hooks.json -verbose -port 8999
[Install]
WantedBy=multi-user.target
3) From the NR container or elsewhere
Now that this URL is launched on the host via the webhook service
It is easy to invoke this URL via the HTTP Request node or a CURL command.
This will cause a reaction on the host and execute the corresponding script.
example (code inside function node)
var ip4 = global.get("ip4");
msg.payload = "http://" + ip4;
msg.payload = msg.payload.replace(/[\r\n]/g, "");
msg.payload = msg.payload + ":8999/hooks/reboot"
return msg;
And the flow:
[{"id":"e936fd79.34d98","type":"comment","z":"77573501.0a8d4c","name":"** DANGER! Reboots the Raspberry ou OrangePi","info":"","x":200,"y":200,"wires":[]},{"id":"2bd9af2a.39e75","type":"ui_button","z":"77573501.0a8d4c","name":"","group":"aaa165da.25ec6","order":4,"width":5,"height":1,"passthru":false,"label":"Reboot Pi","tooltip":"","color":"","bgcolor":"#FF0000","icon":"fa-power-off","payload":"","payloadType":"str","topic":"","topicType":"str","x":160,"y":260,"wires":[["c3350502.fa723"]]},{"id":"404571c0.030c1","type":"inject","z":"77573501.0a8d4c","name":"Reboot Pi à 04h00 du matin","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 04 * * *","once":false,"onceDelay":"","topic":"","payload":"","payloadType":"str","x":180,"y":320,"wires":[["c3350502.fa723"]]},{"id":"c3350502.fa723","type":"function","z":"77573501.0a8d4c","name":"create http request","func":"var ip4 = global.get(\"ip4\");\nmsg.payload = \"http://\" + ip4;\nmsg.payload = msg.payload.replace(/[\\r\\n]/g, \"\");\nmsg.payload = msg.payload + \":8999/hooks/reboot\"\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":260,"wires":[["a59aab7e.a407d8"]]},{"id":"a59aab7e.a407d8","type":"http request","z":"77573501.0a8d4c","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"{{{payload}}}","tls":"","persist":false,"proxy":"","authType":"","x":630,"y":260,"wires":[[]]},{"id":"aaa165da.25ec6","type":"ui_group","name":"Onduleur + Raspberry","tab":"8fc69317.2b6ca","order":8,"disp":true,"width":5,"collapse":true},{"id":"8fc69317.2b6ca","type":"ui_tab","name":"Maintenance","icon":"settings_applications","order":6,"disabled":false,"hidden":false}]
I hope that these explanations will help other people