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 gdb
to 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=0.0.0.0 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 =0.0.0.0 opens up the
debugger to connections from any IP.
By default, the inspector is bound to 127.0.0.1 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.
Comments
Post a Comment
Thanks for your comments!