Debugging with VSCode
As I’m working my way from console.log
statements to appropriate debugging tools I’m writing this post on setting up multi-targeted debugging using VSCode for a Node application running inside a Docker container.
Index
- Requirements
- What happens when a Node process is run in the debug mode?
- Setup Overview
- How to?
- Debug a Node process running inside a Docker container?
- Connect the debugging client (VSCode) to the Node process’ debug socket?
- Get VSCode to reattach the debugger automatically when Nodemon restarts the application inside the container?
- Setup a multi-targeted debugging allowing to debug both the server side and the client side from VSCode?
- References
Requirements
-
Debug client side and server side code (multi-targeted debugging) with the same Debugging Client (VSCode)
-
Debug an application running inside a Docker container
-
Debugging client (VSCode) should re-attach to the process as Nodemon restarts the application on code changes
What happens when a Node process is run in the debug mode?
To debug a Node application it is started with the --inspect
flag.
node --inspect index.js
The --inspect
flag causes the Node application process to listen for debug commands via WebSockets on a default host and port - 127.0.0.1:9229
. A debugging client such as Chrome DevTools or VSCode’s debugger can send the debug commands (set breakpoints, pause, continue, stop) on this socket and also listen for responses.
To debug a node application it is thus required to run it with the --inspect
flag.
Setup Overview
Github Repo for the setup
How to?
Debug a Node process running inside a Docker container?
To debug a Node application running inside a Docker container, the socket (host:port) on which the debugger listens for commands has to be exposed outside the container. To modify the default socket the following command can be used
node --inspect=0.0.0.0:9229 index.js
The debugger has been started on the host 0.0.0.0
and not 127.0.0.1
to make it accessible from outside the container. After executing the above command the debugger is listening on 0.0.0.0:9229
inside the container.
Next, we can map this to the port 9229
on the local machine using the -p
flag in docker run
command
docker run -p 9229:9229 <image-id>
With the above mapping set, the debugger can be accessed on the local machine on 127.0.0.1:9229
. To check if it works go to the following URL in the browser
http://localhost:9229/json/list
Connect the debugging client (VSCode) to the Node process’ debug socket?
-
Go to the root of the project directory.
-
Open
.vscode/launch.json
-
Select the option to ‘Add Configuration’ at the bottom right of the screen
-
Select the configuration for ‘Docker: Attach to Node’. The following default configuration will be added to
launch.json
{
"type": "node",
"request": "attach",
"name": "Docker: Attach to Node",
"port": 9229,
"address": "localhost",
"localRoot": "${workspaceFolder}",
"remoteRoot": "/usr/src/app",
"protocol": "inspector"
},
Modify remoteRoot
to point at the project directory inside the container.
-
Run the Node application inside the container using
docker run
command -
Run the VSCode debugger with the
Docker: Attach to Node
configuration. This should attach the VSCode debugger to the running Node application inside the container.
Get VSCode to reattach the debugger automatically when Nodemon restarts the application inside the container?
Modify the Docker: Attach to Node
configuration in launch.json
and add the following field
{
"restart": true
}
Setup a multi-targeted debugging allowing to debug both the server side and the client side from VSCode?
Setup configuration for debugging JavaScript running inside Chrome
-
Install extension - ‘Debugger for Chrome’ by Microsoft
-
Open ‘launch.json’
-
Select the option to ‘Add Configuration’ at the bottom right of the screen
-
Select the configuration for ‘Chrome: Launch’. The following default configuration will be added to
launch.json
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}",
}
Modify the url
to point to the port where the application is being served. Also modify the webRoot
to point to the public
folder used to host static files.
{
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/public",
}
In my setup I was unable to set breakpoints on JavaScript code inside index.html
wrapped within <script>
tags. I was able to debug .js
files that were loaded into index.html
.
Setup multi-targeted debugging
Setup a compound debug configuration by adding the following to ‘launch.json’
{
"configurations": [
],
"compounds": [
{
"name": "Server/Client",
"configurations": ["Launch Chrome", "Docker: Attach to Node"]
}
]
}
When the debugging session is started in VSCode both the configurations will be launched allowing to debug both the server and the client from VSCode