My test system died yesterday, after a few desperate attempts to downgrade NodeJs. At the end I decided to start using Docker containers. And shortly afterwards I was up-and-running again. My compliments to the Node-RED chef and sous-chef for the nice Docker setup and tutorial!!!!!
Now I would like to start debugging my Node-RED server-side code again. But I'm not sure how to achieve with NodeJs running in a Docker container.
In a non-Docker setup that was very easy:
I needed to start NodeJs in debug mode: node --inspect=0.0.0.0:5858 /usr/lib/node_modules/node-red/red.js
And then I could connect with the Chrome debugger to port 5858
So I can forward port 5858 of my host system to port 5858 of the Docker container, but I'm not sure how to start NodeJs with the --inspect=0.0.0.0:5858 parameter.
Hopefully this doesn't mean I have to start creating (somehow) Docker images by myself?
And from the link in my previous post you can see this:
So I think that first the port is being used by NPM, and afterwards by NodeJS (which will fail because the port is already in use...)? But I don't know how that guy his solution could be implemented in the Node-RED docker container
The "debug" script is almost identical to the "start" script, except it starts NodeJs in debug mode (with the default debug port number 9229). By adding such a second script, I have no impact on production containers!
Then I have build my Docker image (named "testing:node-red-build").
Once the build was completed, I have started a container (from my custom Docker image) via this command:
docker run -it -p 1880:1880 -p 9229:9229 --entrypoint npm testing:node-red-build run debug -- --userDir /data
Remark: I have explained below all the details of this command...
Then I have specified (once) the IP address and port 9229 in my Chrome debugger, and it immediately allows me to start debugging the server-side code (which is running inside the Docker container!):
So it works fine, and I don't think there is impact on non-debug environments.
So now I only need to have the approval of @knolleary and @dceejay, whether this solution is good enough to create a pull request (to add the "debug" script line to the package.json file)? It would be great if I could do all my developments and debugging on Docker containers, since that allows me to setup very easily new clean test environments (e.g. with various NodeJs versions)...
Question: Is it also ok if I add a third script to the package.json file:
The extra " -- inspect - brk" flag will cause Node-RED to break already on the first line of its application code. This allows developers to debug the startup code, which might be useful sometimes ...
Thanks for reading!!!
Here the details of the command to start the Node-RED Docker container in debug mode, for people that want to have more background information:
"Docker run" starts a container.
"-it" (Optional) tells Docker to attach your terminal to the container, so you can see that NodeJs indeed has been started in debug mode:
"-p 1880:1880": Tell Docker that port 1880 of the host system (e.g. Raspberry) should be forwarded to port 1880 of this Docker container. That way you access your Node-RED web-server (which is running inside the Docker container), like you used to do without Docker...
"-p 9229:9229": Tell Docker that port 9229 of the host system (e.g. Raspberry) should be forwarded to port 9229 of this Docker container. That way your debugger (e.g. Chrome, Visual Code, ...) can communicate with NodeJs to do remote debugging.
"--entrypoint npm testing:node-red-build run debug": The Node-RED DockerFile contains the following entrypoint:
This way Docker knows that - when the container is started - he has to execute the command "npm start -- --userDir /data" (which is equal to "npm run start -- --userDir /data"). Which means npm will run the "start" script from the package.json file. But since we want to run our "debug" script instead, we will have to overwrite that endpoint by our own endpoint.
CAUTION: Docker expects the format --entrypoint <executable> <container name> <executable arguments>, which is very confusing (with the container name between the executable 'npm' and his arguments)!
"--" This npm argument tells npm that the next argument won't be an npm argument but that it needs to be passed as an argument to the "debug" script.
"--userDir /data": npm will pass this argument to the "debug" script, which means it becomes an argument for Node-RED. This way Node-RED knows that his data folder (with flow, credentials, ... files) will be the /data folder (in the Docker container filesystem). In the Node-RED documentation, you can see that you can use this folder as a mount point for e.g. the /home/pi/.node-red folder on your host system (i.e. a Raspberry for example).
Please don't hurry. I have now my own private debuggable container which fits my needs until you have time to publish it...
Just out of curiosity: do you need to build the image manually on various types of hardware? Because initially I had accidentally started an AMD build on my Raspberry, which failed. Afterwards I had started an ARM build, which runned fine.
Before this weekend, I wasn't even aware that there were multiple builds for a single image. Had always thought that Docker images where hardware independent
For everybody following this discussion. I have added a wiki page to the node-red-docker repository, which explains how to debug Node-RED (server-side code) via Chrome Developer tools. Note that this also works when Node-RED is running without Docker ...
As usual, all 'constructive' feedback is more than welcome!
Great work for figuring out remote debugging! Thanks!
Later this week I will have a look to get remote debugging feature as part of the official Node-RED images. My idea is to have an environment variable "remote-debug", which can be set to true or false and is false by default. In case it's true, the "script" you provided will be loaded and node-red runs in debug, so a connection from Chrome can be established. This way it's easy for users to toggle between normal and remote debug mode, without building custom images or load specific scripts.