Todd Williams
VP of Technology and Co-founder. Decades of scars from software development and the business surrounding it. Follow @toddewilliams for musings.
Posted on Jul 11th 2016
Hopefully you’ve already read Part 1 of this blog and have successfully learned how to run an application within a Docker container. Now, let’s take it a step further and learn how to debug our application within the Docker container. This blog builds on the example created in Part 1, if you have not read that blog, please take a moment to do so before continuing.
How Can I Debug Inside the Docker Container?
Now that we can run SpringShoppingCartExample in the Docker container, we can easily debug it. All we need to do is update our Docker container so Tomcat debugging is enabled and then connect to it with the MyEclipse debugger.
Enabling Tomcat Debugging in the Docker Container
Our Dockerfile defines a Docker image that creates a container that runs Tomcat in production mode. So to enable Tomcat debugging we need to modify the image definition to do the following:
Run Tomcat in JDPA debugging mode instead of production mode.
Allow remote access to the JDPA debugging port used by Tomcat.
The changes to our Dockerfile look like this:
FROM tomcat:7
EXPOSE 8000
CMD ["catalina.sh", "jpda", "run"]
If you recall, the initial Dockerfile only contained the first line. You might be wondering why we didn’t need to expose port 8080 or include a run
command in the original file. That’s simply because those two things are already done in the base Dockerfile that defines the default Tomcat 7 image we’re using. For the curious, you can see what’s in that Dockerfile here.
Now that we have the image definition we want in the Dockerfile we need to build and tag a new image that we can use for debugging Tomcat instead of just running it. We’ll do that by running the following docker build
command in the Terminal view. You’ll note it’s almost identical to the one we ran in Part 1 of this blog except that we’re now tagging the resulting image as “debug”.
$ docker build -t myeclipse/examples:debug .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM tomcat:7
---> 705d4a88eedc
Step 2 : EXPOSE 8000
---> Running in 955d32a68e5b
---> b7f66dc83d79
Removing intermediate container 955d32a68e5b
Step 3 : CMD catalina.sh jpda run
---> Running in b806ea3bd74c
---> 81ef652e70f5
Removing intermediate container b806ea3bd74c
Successfully built 81ef652e70f5
We can then verify that our image was really built by running the docker images command:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myeclipse/examples debug 81ef652e70f5 8 minutes ago 351 MB
Creating a Remote Debugging Configuration
When we launch our debuggable Tomcat 7 Docker Container we need a way to tell MyEclipse that an external server is running since MyEclipse isn’t directly controlling the container lifecycle. This is done by setting up a new Debug Configuration by using the following steps:
- Select Run>Debug Configurations.
- Select Remote Java Application and then click the New button on the toolbar.
- In our new configuration, we’ll name it Tomcat 7 Docker Container, select the SpringShoppingCartExample as the project, enter the IP address of our Docker virtual machine, and ensure that 8000 is entered as the debug port. When we’re done with the configuration it will look like this:
Once that’s done, click Close and confirm that we want to save the configuration as there’s no need to launch it in debug mode right now.
Putting It All Together to Debug SpringShoppingCartExample
Now that we’ve built a debug image for our Docker container, our application is deployed to a convenient disk location and we’ve created a debug configuration in MyEclipse, we’re ready to put it all together and do some actual debugging.
To begin, we need to launch a Tomcat 7 Docker container based on our debug image definition. Note that the command we’re using is a little different from the one we used in the run configuration. In this command we’re specifying myeclipse/examples:debug as the container image and adding another -p option to map the JDPA debug port (8000) on our container to the same port on the Docker virtual machine (to see it, just hover your mouse over the code below and then scroll to the right).
docker run -v "/Users/todd/Applications/DockerDeployments/SpringShoppingCartExample":/usr/local/tomcat/webapps/SpringShoppingCartExample -p 8080:8080 -p 8000:8000 -d myeclipse/examples:debug
Since we’re debugging, let’s go ahead and set a breakpoint in ShoppingCart.java. I chose line 27 in the addItem method and it looks like this:
Now it’s time to use the debug launch configuration we created earlier to connect the MyEclipse debugger with our Tomcat 7 Docker container. Select Run>Debug Configurations, select the Tomcat 7 Docker Container created earlier and click Debug.
You will notice that when you click Debug nothing really happens. That’s a good thing as MyEclipse only reports if there’s an error during the connection process. So, no news is good news in this case.
Just like in the Run section of Part 1, we’re going to open the MyEclipse Web Browser and navigate to http://192.168.99.100:8080/SpringShoppingCartExample/. We’ll see that the debug version of our Tomcat 7 Docker container is indeed running SpringShoppingCartExample. To hit the breakpoint we set earlier, use the Click here link in the browser and on the next page click any of the add to cart links.
When the breakpoint is hit you may see a dialog that requires you to confirm a switch to the Debug Perspective. Once you do that, you should see something like this:
Of course you can do whatever you’d normally do when debugging, but when you’re doing inspecting the code just click the Play button in the Debug view toolbar to continue.
While we’ve got our container running, I’ll also point out that other cool development features in MyEclipse like LivePreview also work for our deployed application. To test this out, open pagetemplate.jsp in the MyEclipse JSP Editor and arrange the editor area into a horizontal split layout so you can see the web browser at the top and the JSP editor below it. If you did it correctly it will look like this:
In the screenshot above, notice that I’ve changed “Spring Shopping Cart Example” in the editor to “Docker Spring Shopping Cart Example”. Try it yourself and you will notice that as you type in the editor that the change is immediately reflected in the browser. That’s LivePreview.
Hey, We Did It!
Yep, we’re all done. But before we wander off, let’s go ahead and shut down our Docker container so we don’t forget about it. While we could do this like we did before, by using docker ps and then docker stop, below is a bit of command line magic that will simply stop any docker container that is currently running, which is much simpler:
$ docker stop $(docker ps -q)
e9baa9508d21
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Conclusion
You may now embrace your “mad dev skilz” in front of your co-workers to lead the way—if you truly feel the call to build a new awesome reality! If you have any questions or feedback, I’d love to hear from you. Hit us up on twitter at @MyEclipseIDE or on the MyEclipse forum. And, if you’re not already subscribing to our blogs, sign up today!