Dockerizing a Spring Boot Application
Docker, an open-source project released in 2013, is a software platform for building applications based on containers. After its release docker quickly became popular because of the possibilities it opened up for software deployment and delivery. It's famous for its simplicity, fast scaling systems, flexible software delivery, and support for microservices architecture. It’s also at the heart of cloud computing.
During the development phase, it can help to ditch all the additional setups your application will need by just creating the needed containers. By dockerizing your application you can share your project with anyone and if they have docker installed it’s good to go. In this article, you’ll see how easily you can dockerize your spring boot app and debug it. So let’s get started.
Requirements
- Any working spring boot application
- Basic understanding of docker
- Installed docker desktop
- Intellij IDE
- HeidiSQL for DB
- Postman to test API
Project build
Open the spring boot application and build it. Here this project is an API, to query data from a MySQL DB. Any application will work for this article, as long as it’s producing an executable jar format. To build the project you can use either the UI maven menu
Or you can use the mvn command
mvn clean install
After a successful build, if you look at the pom.xml during the build step with the spring-boot-maven-plugin it creates a jar file in the target folder. So we can just run it with the java jar command. Open a terminal and go to the target folder
cd target/
java -jar bookAPI-1.0-SANPSHOT.jar
To dockerize our application we’ll copy and run this jar inside a docker container. For the API to respond with data we’ll need the DB up and running so let's start by creating the mysql db service.
Docker compose
Since this is a multi-container application we’ll be using docker-compose. To create a compose file for this application we’ll need 2 services:
- API
- MySQL DB
Go to the root of your project and create a docker-compose.yml file.
DB Service
We start by defining the compose file version. A compose file consists of services, volumes, and networks. Here, I started by defining the db service.
book-mysql: service nameimage: base image for creating the containercontainer_name: name of the containervolumes: to persists the sql, with format hostFileLocation:containerFileLocationports: to expose port mapping with format
hostPort:containerPortenvironment: to set env variables in this service's container, here password for the mysql dbhealthcheck: to test the container health by running a command at specified interval for timeout
Let's run and see the container in action
docker-compose up -d
Here in the logs, we can see that the container has started correctly with the copied SQL. When no network is defined docker creates a default network for each container to join. You can connect to the DB container using the host mapped port and login as defined in the compose file.
It looks good with the data added along with the executed script. Now let's create the service for the API.
API Service
To run any jar application the service needs a JDK so I started by defining the JDK image. Then copy the jar from the target folder and run it with the java jar command just as we saw previously in the building part. Since the API won’t be much of use without a DB so I defined its dependency on the DB service.
book-api: service nameimage: you can create your own base image by a Dockerfile to create image or use an existing one, like the openjdk11 image herecontainer_name: name of the containervolumes: to persists the jar inside the conatiner with format hostFileLocation:containerFileLocationcommand: to provide a default entrypoint by run the copied jar, accepts an array of stringsports: to expose port mapping with format
hostPort:containerPortdepends_on: specifies service dependency on book-mysql service/container, will not start book-api if mysql fails
Now change the spring data source in the application.properties with the service name so spring will be able to find it.
let’s build the project and open a terminal to test the containers.
docker-compose up -d
Thanks to the docker plugin in Intellij you can check the container logs in the service tab. From the container logs, we can see that the application has started correctly.
Now open postman and test the response of our API to be sure everything works correctly.
To stop and remove all the containers use compose down command
docker-compose down
Debugging
Debugging is an important part of any application development. To debug our jar API first, we need to configure JVM to enable debugging. To do that use the following command in the docker-compose file and add the debug port mapping.
command: ["java","-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:debugPort","-Dspring.profiles.active=springProfile","-jar","bookapi.jar"]
ports:
- "8080:8080"
- "5252:5252"
Now create a remote debug configuration in IntelliJ with the specified debug port.
By doing this you have two options to connect to the debugger. First by clicking on “Attach debugger” at the start of container logs
Or by clicking on the debug configuration of Intellij that we created earlier.
Let’s debug with a breakpoint by making a request from the postman.
It works as expected. I hope this will help you to dockerize and debug your spring boot application. You can find this project here on Github.
Happy Dockerizing!!