Debug nodejs Application In Docker Container Using WebStorm - Part 3
In the part 1 of this series we implemented a simple RESTful service that simply responds with "Hello, world!". We also demonstrated hitting a breakpoint. In part 2 we containerized our app and demonstrated that we could run it in a Docker container without a single change.
In this third part we'll build on that by adding the configurations required so we can hit breakpoints while our app is running inside of a Docker container. As a reminder you can find the source code for this tutorial on github.
Debugging nodejs Remotely
A container is separate from our local environment. It's not a virtual machine but better described as a minimal runtime environment. We don't really need to understand a container other than knowing that it provides just the elements our RESTful web service needs and nothing else.
To debug a nodejs application that runs inside a container we need to be able to connect to it remotely. For that we'll tell nodejs that it is being debugged and what port it should use to connect with the debugger.
Configuration Changes
We don't need to change anything in our applications code. All changes that we need are in the Dockerfile and the docker-compose file.
docker-compose.yml
Let's start with docker-compose.yml. We already have one entry for mapping port 3100 to 3000. We need an additional port for the debugger. You can use any port if you like but let's keep it simple and stick with the default which is 9229. This time we don't need to distinguish between running locally or inside of the container. We don't connect remotely if we run locally. We only need this when running inside of a container. Here is the new version of the file "docker-compose.yml":
Note that in line 13 we added the mapping for port 9229. Both numbers, internal and external, are the same in this case.
Dockerfile
We also need to make a change in the dockerfile. Here we need to instruct nodejs to allow a debugger to attache. This is done with the options "--inspect" and "--inspect-brk". You will find material on the internet that suggest the use of "--debug" and "--debug-brk". It depends on the version of nodejs you are using. The variants with "debug" have been deprecated from nodejs version 8 onwards.
Also, there are contradicting statements as to what IP address to use for "--inspect". There as at some point even some confusion within the nodejs developer community. However, I found this comment that provided the solution. The IP address needs to be "0.0.0.0".
With these two changes in place we need to rebuild our docker image and then our docker container. First we need to bring down our container, though. First step is "Ctrl+C" in the terminal window within WebStorm. Then execute the command "docker-compose down":
Next we need to build the image again with "docker-compose build" and then start up the container with "docker-compose up".
The container is running again, this time using the new image and therefore all is prepared to connect with the debugger.
Next we need to build the image again with "docker-compose build" and then start up the container with "docker-compose up".
The container is running again, this time using the new image and therefore all is prepared to connect with the debugger.
WebStorm Debug Configuration
Before we can use WebStorm to connect to our app running within the Docker container we need to tell WebStorm how to do that. The machanism is called a "Debug" configuration. To create it, within WebStorm click "Run", then "Edit Configurations...".
- Click the plus sign in the upper left corner
- Select "Attach to Node.js/Chrome"
WebStorm will then create a new unnamed configuration. On the right hand side enter "Nodejs Remote" as the name for the new debug configuration. Also make sure you choose to use "Attach to" as "Chrome or Node.js > 6.3 started with --inspect". Leave the rest as-is.
Debug Session
Now we'll start the most interesting part. To have a clear starting line, run again the command "docker-compose down" in WebStorm's terminal window. If you have curl installed on your box, you can also test "curl localhost:3100" to confirm the web server is no longer responding. You can also use the command "docker container ls" to see if the container has been deleted.
Then within WebStrom rightclick on the file "docker-compose.yml" (don't use "Dockerfile") and the select "Run Dockerfile". You can achieve the same by entering the command "docker-compose up" in WebStorm's terminal window.
Then in the upper right corner of WebStorm make sure you have selected the run/debug configuration "Node.js Remote" that we created earlier. Then click the green "bug" symbol. This will launch the debugger and connect it to the running container.
The screenshot shows the debugger having stopped execution. This is because we added the option "--inspect-brk" which instructs nodejs to wait for a debugger to attach before continuing execution. Just click the green rightward facing triangle to continue execution.
Next it will hit the break point in line 9 of file "hello_express.js" which I also set to see the startup behavior.
Again, click the "Continue" button. WebStorm will show that it's connected to localhost:9229, which is the debug port that we specified.
Now, let's see if we can hit the other break point in the function that handles the HTTP GET request for "/". You can use again the "REST Client" - or - use command "curl localhost:3100" in a terminal window.
Summary
Although it took me three parts to describe how to get to this point, in essence setting up a nodejs application running inside a container so that we can debug it using WebStorm is not very time consuming if you know what the relevant configuration steps are. I hope that I provided enough details so that you can replicate the setup in your environment and for applications that do more than just printing "Hello, world!" in a terminal window.
Please post questions for clarification as comments to any one of these posts. I'll try my best to answer them.
Bonus
Once you have the container running that exposes the debugging port 9229, you can also try this command in a terminal window: "curl localhost:9229/json/list". The output can potentially be of value or at least provide some incentive to get your curiosity going!
A Word Of Caution
Actually, two works. Firstly, do not expose the debug port in any production deployment as it will open up a backdoor for potential attacks. It's meant for development only. Also, don't deploy your nodejs application with NODE_ENV set a value other than "production" for performance reasons.
The second parting comment is with regards to debugging inside of a container. Generally you should not need to do that for most of your code if you use a test-driven approach and can test your classes in isolation. A container adds only an extremely thin layer around it. Once the container works and all your tests pass, you should be good to go and not experience any issues in general. Using a container can slow you down if you use it in the manner described in this series of posts.
Happy coding!









Comments
Post a Comment