We all need to debug node program from time to time. If you are using VSCode as your IDE, it’s pretty straightforward.
Debugging with local files is even more comfortable. However, when you need to debug node program in a container, there are a few caveats need to notice.
Let’s start with a few js lines and Dockerfiles. (You can also clone this repo).
Or, skip to TL; DR :)
Get Started#
index.js#
const sleep = seconds => new Promise(resolve => setTimeout(resolve, seconds * 1000));
sleep(10)
.then(() => {
console.log("The waiting is over!");
});
Dockerfile#
FROM node:12-alpine
WORKDIR /app
RUN apk add --no-cache tini
COPY package.json index.js ./
ENTRYPOINT ["/sbin/tini", "--"]
CMD node index.js
Dockefile_node5#
FROM node:5
WORKDIR /app
COPY package.json index.js ./
CMD node index.js
What you can see here, are two different versions of node. If you are going to debug with older node versions, you will have to change the protocol and the port.
The following launch.json
will let VSCode how to attach to the code in the container properly.
launch.json#
{
"version": "0.2.0",
"configurations": [
{
"name": "Docker: Attach to Node Version >= 7.7",
"type": "node",
"request": "attach",
"localRoot": "${workspaceRoot}",
"remoteRoot": "/app",
"protocol": "auto",
"port": 9229
}
]
}
Build images and run containers#
Now we have 2 Dockerfiles with different node versions; we need to build these images before we can run it.
$ docker build -t debug-demo . # Build image with Dockerfile
$ docker build -t debug-demo:node5 . -f Dockerfile_node5 # Build image with Dockerfile_node5
Let try node 12 first, copy the launch.json
above into your configuration. And set breaking point at line 5.
Then start the container:
$ docker run --rm -p 9229:9229 debug-demo node --inspect=0.0.0.0 index.js
And start debug session with the green arrow:
When the bottom bar turns to orange, then it’s successfully attached to the container.
A few seconds later, you will see that line 5 has been highlighted. Seems familiar right?
But do we need to make the program to wait for a while before we can attach them?#
No, of course. That’s where another useful argument --inspect-brk
comes in. Let’s change the --inspect
to --inspect-brk
:
$ docker run --rm -p 9229:9229 debug-demo node --inspect-brk=0.0.0.0 index.js
And start the session again:
The program now stopped at the very beginning. After VSCode attached to it, you can go to any point you want.
What if I am still using an older node version (<= 7.6)?#
Then you need to have some configurations changed. Remember that the protocol and the port mentioned above? That’s what we need to modify.
{
"name": "Docker: Attach to Node Version <= 7.6",
"type": "node",
"request": "attach",
"localRoot": "${workspaceRoot}",
"remoteRoot": "/app",
"protocol": "legacy", // specify legacy instead
"port": 5858 // not 9229 anymore
}
Change the configuration:
Start the container:
$ docker run --rm -p 5858:5858 debug-demo:node5 node --debug-brk index.js
Things to remember here:
- When you are debugging using the old protocol, you need to expose different port
5858
instead of9229
. - The argument is
--debug
(or--debug-brk
) instead of--inspect=0.0.0.0
(or--inspect-brk=0.0.0.0
).
Finally, let’s debug!
TL; DR#
Run your container#
Node version <= 7.6
$ docker run --rm -p 5858:5858 <IMAGE> node --debug-brk <ENTRY_POINT>
$ docker run --rm -p 5858:5858 debug-demo:node5 node --debug-brk index.js # Example
Node version >= 7.7
$ docker run --rm -p 9229:9229 <IMAGE> node --inspect-brk=0.0.0.0 <ENTRY_POINT>
$ docker run --rm -p 9229:9229 debug-demo node --inspect-brk=0.0.0.0 index.js # Example
launch.json#
{
"version": "0.2.0",
"configurations": [
{
"name": "Docker: Attach to Node Version >= 7.7",
"type": "node",
"request": "attach",
"localRoot": "${workspaceRoot}", // make sure the path is correct
"remoteRoot": "/app", // make sure the path is correct
},
{
"name": "Docker: Attach to Node Version <= 7.6",
"type": "node",
"request": "attach",
"localRoot": "${workspaceRoot}", // make sure the path is correct
"remoteRoot": "/app", // make sure the path is correct
"protocol": "legacy",
"port": 5858
}
]
}