Debug nodejs Application In Docker Container Using WebStorm - Part 1
First some housekeeping: I'm using the following versions of tools and libraries:
- Windows 10 Professional, latest updates as of 19 Aug 2018
- Node.js 8.11.3
- Node.js 8.11.3
- WebStorm 2018.2
- Docker for Windows, Community Edition, version 18.06.0-ce-win72 (19098), channel: stable
Introduction
WebStorm is a great IDE for developing applications based on nodejs. Docker is a great technology to develop microservices. While often you can run your code and tests without firing up a docker container, I was curious to find out if I could create a simple "Hello, world!" app, set a break point, run it in a container and then hit that break point. That turned out harder than I thought because of changes between versions of nodejs, changes of WebStorm dialog boxes, and similar more.
Obviously, if all your app is doing is printing "Hello, world!" somewhere then using Docker would be a total overkill. Don't do it! For something that simple it would result in a Rube Goldberg machine.
In this tutorial - which will probably consist of multiple parts - we'll take one step at a time. I'll then walk you through each file as I create them. You can find the source code for this tutorial on github including tags for each of the parts. Let's get started.
Hello, World! via REST
The application is extreme simple: We'll call it hello-express. Open WebStorm, then go to "File" - "New" - "Project..." which will open the "New Project" dialogbox. Create the project at a location of your choice and name it "hello-express" as shown in the following screenshot:
- Select "Empty Project"
- Enter a path plus the name of the project "hello-express"
- Click "Create"
WebStorm will then create the new project for you, either in the current WebStorm window or in a new one, subject to your settings in WebStorm. If you're not asked if you want to open it in a new window then WebStorm will just close the previous project (if any) and open the new project (which is essentially a folder in your file system).
The first file will contain the code for firing up a web server and describing what to do with a HTTP Get request for "/". To create it, right-click on the "hello-express" folder within your project and select "New" and then "Java Script File". As a file name enter "hello_express.js" with an underscore instead of a hyphen. Once created you may need to expand the "hello-express" folder in your project. The file will be empty. Copy and paste the following code into the new file.
In line 1 we import the express library. Express is a "Fast, unopinionated, minimalist web framework for node". Effectively, it's an implementation of a web server.
In line 2 we instantiate the express app and assign it to the variable 'app'.
Lines 4 to 6 tell the app what it should do if there is a get request for "/", i.e. the root of the application. We'll later execute a request for "localhost:3000/". When such a request arrives, our code will just write "Hello, world!" to the response object ('res'). The other parameter for the handler function is 'req' which represents the HTTP request. We are not using that object in this example.
Lines 8 to 10 tell the app to listen on port 3000. When this executes we just have it write a message to the console, so that we know our web server is ready to respond to requests.
Once the file has been created you might be tempted to start it by right-clicking and selecting "Run 'hello_express.js'" or "Debug 'hello_express.js'". This will fail because it doesn't know yet where and how to get the 'express' module.
Therefore our next step is adding a file that lists the dependencies for our project, i.e. packages or modules it needs to run. For that we effectively turn our little app into a package itself by adding a file named "package.json".
Within WebStorm right-click on the "hello-express" folder and then select "New" and then "package.json File". It will create a new file and offer to overwrite some default values. Just press "Enter" to accept those. Then within the dependencies add an entry for "express". It may suggest a different version but for the purpose of this tutorial please choose "~4.16.3". If you want to understand what the tilde "~" means, please check out this description. Effectively we want version 4.16.3 but allow all versions 4.16.x where x is equal or greater than 3 excluding any pre-releases. In essence, we allow for patches that may have been released later but we don't want any new features.
In file "package.json" we specify the name of the package in line 2 and the version in line 3. In lines 4 to 6 we list the dependencies that we need for running our application. You can have another section that describes dependencies that you need only for development but we don't need that for this example.
Once you have save "package.json" WebStrom may suggest to run "npm install". "npm" is a nodejs package manager and the command "npm install" checks for the "package.json" file in the current directory and installs the packages listed in "package.json".
If WebStorm does not suggest to run "npm install" (perhaps you told it to not ask again), then you can also right-click on the file name within the project window of WebStorm and then select "Run 'npm install'". That's what we'll do next and wait for WebStorm's run window to show "Process finished with exit code 0". You can ignore the warning message regarding the missing license field. It doesn't affect us for this example.
Once "npm install" has completed, you will notice that a file named "package-lock.json" has been added to your project. You can ignore this file for this example as it won't affect us. However, if you are curious about what it does then have a look at this description.
At this point we have installed the packages required for running our app. Right-click on "hello_express.js" and choose "Run 'hello_express.js'". This time this should work and in the "Run" tab you should see the message "Example app listening on port 3000!".
To test if this really works we'll use a WebStorm tool for testing RESTful web services. Within WebStorm select "Tools", then "HTTP Client", then "Test RESTful Web Service". This opens a tool windows named "REST Client". In my installation is says "depricated" and I tried the new format but didn't find that as useful at this stage. I'm sure the new version will become more intuitive over time.
If WebStorm does not suggest to run "npm install" (perhaps you told it to not ask again), then you can also right-click on the file name within the project window of WebStorm and then select "Run 'npm install'". That's what we'll do next and wait for WebStorm's run window to show "Process finished with exit code 0". You can ignore the warning message regarding the missing license field. It doesn't affect us for this example.
Once "npm install" has completed, you will notice that a file named "package-lock.json" has been added to your project. You can ignore this file for this example as it won't affect us. However, if you are curious about what it does then have a look at this description.
At this point we have installed the packages required for running our app. Right-click on "hello_express.js" and choose "Run 'hello_express.js'". This time this should work and in the "Run" tab you should see the message "Example app listening on port 3000!".
To test if this really works we'll use a WebStorm tool for testing RESTful web services. Within WebStorm select "Tools", then "HTTP Client", then "Test RESTful Web Service". This opens a tool windows named "REST Client". In my installation is says "depricated" and I tried the new format but didn't find that as useful at this stage. I'm sure the new version will become more intuitive over time.
- Choose "GET" for the HTTP Method
- Enter "http://localhost:3000" for host and port. Note that we use port 3000 here since that is the port we told our app to listen on.
- Enter "/" for the path
- Click the green triangle on the left to run the request
As s result it should now switch to the response tab which shows "Hello, world!"
We are not quite done yet. We also want to be able to set a break point which we then want to hit when we execute the program. In file "hello_express.js" set a breakpoint in line 5 by clicking in the gutter. WebStorm should now show the file like this:
Next, we need to run the program under the debugger. Within WebStorm right-click on "hello_express.js" and choose "Debug 'hello_express.js'". In case WebStrom prompts you telling you "hello_express.js" is already running choose "Stop and Rerun".
The "Console" tab of the "Debug" window should show you a message that the debugger is listening on some port with a URL that includes a UUID (aka GUID on Windows). And it should again show the message "Example app listening on port 3000!".
You will see a different port and UUID in your environment. That's not a problem as WebStorm will be able to work this out. If the screenshot is too small to read, you can click on it to enlarge it.
Now click again on the "REST Client" tab at the very bottom of the WebStorm window. Then click again the green triangle on the left. The values for method, host, port and path should still be the same:
WebStorm will now stop the execution at the breakpoint and show values of the variables in scope, e.g. "req", "res". This is exactly what we wanted to accomplish.
We now know that we can hit a breakpoint in our app without Docker in the picture. In the next part of this two-part post we'll turn it up a notch by running the same thing inside a Docker container.
To conclude this part, click on the red square to terminate the debugging session. That also stops the node process with our code and therefore it also stops the web server.
Go to part 2
To conclude this part, click on the red square to terminate the debugging session. That also stops the node process with our code and therefore it also stops the web server.
Go to part 2
Comments
Post a Comment