Debug Nodejs inside Docker container Debug Nodejs inside Docker container docker docker

Debug Nodejs inside Docker container


I managed to make it run here. I wish I could run node-inspector as a sidekick container, it would be so clean(EDIT: It is possible, see end of answer). Unfortunately, looking into node-inspector sources, it is not possible to run node-inspector remotely(because node-inspector needs to access files so it can display them) so even container linking is out the window. Maybe it will support it at some point.

Here's is my solution:

In Dockerfile, install node-inspector. I decided to make it global so I can use the same container to debug all my apps.

RUN npm install -g node-inspector

Instead of lunching node in the CMD command, use a bash script that will let you launch more than a single process. This is not the Docker way but as I stated, limit in node-inspector prevent us from using sidekick container. You could also use a more robust solution for process management like supervisor but for debugging a simple script is enough in my opinion.

CMD ["/bin/bash", "start.sh"]

This script checks for the presence of a DEBUG environment variable to launch node and enable debug.

#!/bin/bashif [ -z ${DEBUG+x} ]; then  node server.jselse  node-inspector --web-port 9080 &  node --debug server.jsfi

I guess you could use the same trick to install or not node-inspector. You can even have conditional statement in RUN command if you want to skip the script for installation.

Then when you want to debug a container, launch it like so:

docker run -d -P -p 9080:9080 --env DEBUG=1 --name my_service \    -v /home/docker/sources/.../:/usr/src/app custom-node

Now you just need to hit the docker daemon ip for debugging since we exposed the debug port specified in the script(9080) on the docker run command. My Dockerfile already exposes my main port so I used -P for that.

If your container runs on a local VM and you are setup behind a proxy, make sure it either support local addresses or that you disable it before debugging.


EDIT: now works with sidekick container

Here's is the content of my node-debug container Dockerfile

FROM node:4.2.1EXPOSE 9080RUN npm install -g node-inspectorCMD ["node-inspector", "--web-port", "9080"]

Docker provides us 2 features to make it as if node-inspector was running locally with the node process.

  1. Even though node-inspector seems to imply you can connect to remote machine by telling you to connect to 127.0.0.1:8080/?ws=127.0.0.1&port=5858, I couldn't find any code that was parsing the ws parameter so I used docker net config option to pop the node-debug container in the same network stack as my debugged process: --net=container:mysvc. This way, node-inspector can open the websocket connection to localhost:5858.

  2. By using the same mount point as your debugged process, you can fake file locality to the node-inspector process.

Now to make it a little more convenient, I would suggest to use data container for your app sources.

If you want the possibility to start node in debug or not, continue to use the start.sh script(remove the node inspector command though). I wonder if we could use a signal with docker though, that would remove the dependency on start.sh entirely.

if [ -z ${DEBUG+x} ]; then  node server.jselse  node --debug server.jsfi

So create the data container:

docker create -v /home/docker/sources/.../:/usr/src/app  \    --name my_service-src custom-node /bin/true

Launch node app and expose node-inspector debug port:

docker run -d -P -p 9080:9080 --env DEBUG=1 --name my_service \    --volumes-from my_service-src custom-node

Launch node-debug container:

docker run -d --net=container:my_service --volumes-from my_service-src \    --name node-debug node-debug

This way, you can quickly spawn node-debug container on the fly to debug a node process.

Connect to docker ip and enjoy your debugging session !


After struggling for a while to get this to work, I found that adding:

--inspect-brk=0.0.0.0:9229

instead of just the usual inspect-brk

made things work.

You'll also need to map your ports correctly in your docker run command:

-p 9229:9229

Full example:

docker run -ti -p 3000:3000 -p 9229:9229 -v `pwd`:/app/ myImage bashnode --inspect-brk=0.0.0.0:9229 /app/index.js

Then go to chrome://inspect

And hit "Open dedicated DevTools for Node" and it should all work :)


Using two different images for debugger (node-debug) and app server (custom-node) has no sense in this case. As custom-node container needs node-inspector binaries to be installed too. Otherwise a Cannot find module '/usr/lib/node_modules/node-inspector/lib/InjectorServer.js' error is pushed into node-inspector client-side console and nothing is being debugged as well.