Developing Spring Boot Applications in Docker locally
with a focus on giving a great developer experience and productivity
Docker provides an unprecedented way of creating portable dev environments which are quick to set up and easy to extend. Creating containerized applications has the promise of the lowest dev/prod parity. However, any developer would take the path of least resistance when it comes to day-to-day coding workflows. The instructions provided for containerizing the spring boot applications often lack the focus on doing so on the local dev box. These also are not tested on all the three commonly used operating systems — Windows, OSX, and Linux. This tutorial aims to bridge the gap.
Step 1: Download and install Docker
Unless you already have Docker installed, you can download and install it from https://docs.docker.com/get-docker/
Step 2: Create a Spring Boot Application
You can use the web-based Spring Initializr or a different method to create a spring boot application.
I have added three dependencies for the purpose of this tutorial:
- [Required] Spring Boot DevTools — Provides fast application restarts, LiveReload, and configurations for enhanced development experience.
- [Optional] Spring Reactive Web — Build reactive web applications with Spring WebFlux and Netty.
- [Optional] Lombok — Java annotation library which helps to reduce boilerplate code.
Here are the maven dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Step 3: Develop code inside Docker
Following are some capabilities that we wish to have:
- Being able to develop code available in your local file system using an IDE such as IntelliJ Idea, VSCode or Eclipse (or STS)
- Avoid having to compile on the host
- Being able to automatically build and deploy changes to without having to manually build or restart the application
The first step is to create a Dockerfile at the application root.
Eclipse Temurin is the base image having the Open JDK 11 installed on a Debian OS.
The utility called “inotify-tools” helps monitor changes in the code.
We use “dos2unix” to workaround to normalize the line endings in files created in Windows and make them able to run inside the unix-based container.
Create a run.sh file to help automate the tasks to be run at application boot-up
The local source code directory is mounted inside the container at the path /app
A container’s local storage is supposed to be volatile. We would hate to lose our maven dependencies which can take a few minutes to cache the first time when we run the application. So, we have mounted the .m2 directory from inside the container to be available as a local directory on our local file system. This will allow you to destroy the container and recreate it without hassle.
The following ports are exposed:
- The application runs on port 8080.
- Port 35729 allows the livereload plugin to listen to changes
- Port 5005 makes the debugger available to the IDE
The docker image can be built using the command
docker-compose build
and the container can be run using the following
docker-compose up
Step 4: Debugging with your IDE
I’ll use IntelliJ Idea for the demonstration. Search for “remote debugging” in the context of your favorite IDE to find the instructions for your workflow.
Edit the run configurations
Add new configuration
Choose “Remove JVM Debug”. The default options should work. Here’s what my configuration looks like:
Now select your new remote configuration from the dropdown and hit the debug button
Here’s what a successful console output looks like
Now add a breakpoint and run your API. It should hit your breakpoint.
Make some changes to the codebase and observe that the code rebuilds automatically.
Resources
The source code for this tutorial can be found on https://github.com/v1bh0r/spring-boot-local-dev-docker/
Troubleshooting
Most of the issues that I have encountered with the setup have been around volume mounts on Windows.
You might face issues such as permission errors on the mounted source code or the code changes not triggering a re-build automatically.
Being aware of if you are using Hypervisor or WSL1 or WSL2 is the key to solving these issues.
Vibhor Mahajan is the VP — Software Product Development and Innovation at Trantor. His job at Trantor is to establish trust with new challenging accounts, develop novel practices, and scale software engineering teams. He provides consulting and thought leadership to help establish consistent and sustainable software engineering delivery.