Debug a Node.js application in a Docker Container

In this post, we'll take a look at how you can debug a Node.js app in a Docker container.

According to the Foundation's Node.js Developer Survey, half of Node.js users use Docker for development because containerization, in general, is a very powerful tool.

Using the Node inspector

If you mostly use printf, aka caveman debugging, it can be very difficult to find the right value at the right time.
Things get even worse if you have to rebuild your container image each time you add console.log to it. It could be a lot easier to have the image built once and jump around within it, examining your variables while it's running. To better understand what we're gonna do here, I highly suggest to familiarize yourself with the node inspect commands first.

To run your Node app in debug mode, simply add inspect after node, something like that:

When you run your code in inspect mode, it always stops at the first line, waiting for you to interact with it.

For those who were brought up using gdbto debug their code, this interface might be compelling. However, if you are used to interacting with your debugger using a GUI, you might want to open up your chrome and navigate to chrome://inspect.
You should see something like this:

Under remote target, click inspect and you'll be presented with the Chrome Developer Tools debugger.

Now you can use the debugger as you please. It's time to wrap our app in a container.

Debugging in a container:
First, we'll need to create a Dockerfile,
and a docker-compose.yaml
Now if you run docker-compose up, you'll be able to reach your service on http://localhost:3000.

The next step is to expose the debug port to the outside world. First, let's create a debug-compose.yaml.
As you can see, we opened up port 9229, which is the debug port of Node.js apps. We also overrode the command we specified in the Dockerfile. The --inspect-brk= argument does two different things:
1.     --inspect tells Node that we want to run our app in debug mode.
2.     by adding -brk we also make sure that the app stops at the first line, so we have enough time to open up the inspector
3.     adding = opens up the debugger to connections from any IP.
By default, the inspector is bound to which makes sense, as we usually don't want to allow people from all around the world to attach a debugger to our app. However, the container is a different host with a different IP than our host machine, so we won't be able to reach it. It is fine as long as we do it locally; however, we don't want to run it on a live server like this.
For this reason make sure it is a different file from your docker-compose.yaml.
With a bit more work, you can expose the debug port from your staging cluster to your IP — but in that case, to your IP only — and debug issues there as well.
Also, note that the port forwarding rules are enclosed in "-s. If you omit the quotes the rule might not work, making it difficult to figure out why you’re unable to attach the debugger to your process.


Popular posts from this blog

What’s the difference between AngularJS, Angular2 and Angular4?


Efficiency of an algorithm