posts

How to Dockerize a Spring Boot Application

figure
Jun 21, 2022
Md Kamaruzzaman

A guide to building Java microservices. Part 2

Welcome back to developing cloud-native applications based on microservice architecture. In the first part of the series, we built sample Spring Boot microservices and prepared them for deployment in the cloud. Now it’s time to containerize our Spring application with the help of Docker, a platform for building, deploying, replicating, and shifting container images.

As always, you can use convenient copy-and-paste code snippets below to follow along. And remember that if your company needs expert advice on cost-efficient deployment of Java applications in the cloud, you can always turn to BellSoft engineers for help.

  1. Set up cloud-native infrastructure
  2. Containerize an application using Docker
  3. Conclusion

Set up cloud-native infrastructure

The beauty of microservice architecture is that we can create services in different programming languages. However, multilingual projects are not a golden standard, so for the sake of enhanced stability and performance it is better to standardize your application and use a unified stack of technologies.

With that in mind, we are going to concentrate on Java as the primary language for our microservices. To learn more on the topic why Java is perfect for creating cloud-native microservices, refer to Introduction to Cloud-Native Java, a DZone Refcard by BellSoft. And we are moving on.

To deploy our Spring application to the cloud, we need to build infrastructure, which includes Docker and Kubernetes. Docker allows you to to package an application with all of its dependencies into a container and share it across various environments, while preserving security of an isolated system. Other advantages of Docker:

  • The possibility to update certain parts of code without the need to take down the whole application;
  • Layered images with layers that can be reused for creating new containers;
  • Automated deployment;
  • The possibility to roll back to the previous version of an image.

Spring Boot offers Cloud-Native Buildpack that generates a Docker Image from a Spring Boot project. Spring Boot also uses BellSoft Liberica JDK as a default JVM for Java applications. Docker enables the deployment into the cloud.

One way to deploy a Spring Boot application or a single microservice in the AWS cloud is by using Docker to create containers with the OCI image format, Amazon ECR as a managed container registry (Docker repository), and Amazon EKS as a managed Kubernetes service. Another way for this is going with AWS Elastic Beanstalk, which offers a Platform as a Service (PaaS) to deploy web applications in the AWS cloud in a managed, auto-scalable way. But this post won’t touch on it.

Unfortunately, for our purposes of a quick demo, we cannot elaborate on other aspects of cloud computing, such as continuous integration/continuous delivery, the classical Java EE way of thinking realized in MicroProfile, building a complex distributed system, and so on. So for now let us focus on the task at hand, namely containerization.

Containerize an application using Docker

First, make sure that Docker is up and running. For details on installing and setting up Docker on your PC, refer to the documentation on the official website.

We are going to use the Spring Boot application we created in the first part of the series. However, if you didn’t follow the series, feel free to visit Spring Initializr and create your own demo application for the purposes of this article. Choose project type, Java version, and add Spring Web dependency as shown in the screenshot below:

Creating a Spring Boot demo app

Configure your SpringBootDockerApplication in the following way:

@SpringBootApplication

@RestController

public class SpringBootDockerApplication {

  @RequestMapping("/")

  public String home() {

     return "Hello from Docker!";

  }

  public static void main(String[] args) {

     SpringApplication.run(SpringBootDockerApplication.class, args);

  }

}

Now, there are two ways of building Docker images. You may build a Docker image by defining a Dockerfile where the various layers of the Docker image need to be defined. The downside of this approach is that creating a Dockerfile needs a good understanding of the Docker technology. To empower the containerization, Cloud Native Buildpacks by Pivotal transform your source code into an OCI (Open Container Initiative) compatible Docker image without the need of a Dockerfile. The Docker container image can then be deployed in any modern cloud.

Paketo.io is a Cloud Foundry project and one of the most popular implementations of Cloud Native Buildpacks. It can transform the source code of major programming languages into a container image.

Spring Boot natively supports the buildpacks that create an image with BellSoft Liberica JDK. It also looks at the build.gradle file and the Spring configuration file to build the Docker image.

Go to the Customer or your Spring demo application directory and run

./gradlew bootBuildImage

If you built your app using Maven, run

./mvnw spring-boot:build-image

The command will build a Docker image. For our demo, the Customer microservice container image looks as such: docker.io/library/microservice-customer:1.0.0

Then we create one for the Order microservice going through the similar step: docker.io/library/microservice-order:1.0.0

We can run the microservice with a Docker command — here’s one for the Customer microservice:

docker run -d -p 8080:8080 docker.io/library/microservice-customer:1.0.0

And here is one for your Spring demo app:

docker run -d -p 8080:8080 springio/gs-spring-boot-docker

Visit the http://localhost:8080 to make sure that your application is running. Although Docker Desktop for Apple Silicon is available as a GA release, you need to install Rosetta to run Docker images. For further information on running Java applications in Docker on Apple Silicon, read our article dedicated to this topic.

If the Docker container started successfully, you’ll see the container ID as follows (in your case, it will be different as it is a unique ID):

c1c3925595047ff5744507dd0abc05b1063f7dc884c3e2a4c9864633a2780d2b

Now, the following lines will appear in the Docker container log file:

> docker logs c1c3925595047ff5744507dd0abc05b1063f7dc884c3e2a4c9864633a2780d2b

2021-03-03 22:01:21.116  INFO 1 --- [ngodb.net:27017] org.mongodb.driver.cluster           	: Setting max set version to 2 from replica set primary clustermicroservice-shard-00-01.fzatn.mongodb.net:27017

2021-03-03 22:01:21.116  INFO 1 --- [ngodb.net:27017] org.mongodb.driver.cluster           	: Discovered replica set primary clustermicroservice-shard-00-01.fzatn.mongodb.net:27017

2021-03-03 22:01:21.184  INFO 1 --- [       	main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'

2021-03-03 22:01:21.240  INFO 1 --- [       	main] o.s.b.a.w.s.WelcomePageHandlerMapping	: Adding welcome page: class path resource [static/index.html]

2021-03-03 22:01:21.383  INFO 1 --- [       	main] o.s.b.w.embedded.tomcat.TomcatWebServer

Please note that we are using the port forwarding (-p 8080) so that we can connect with the containerized microservice from outside (e.g., from a local machine).

It is possible to check whether the Docker container is running by sending a GET request to its liveness or “health” endpoint as described in detail in Part 1:

    curl --location --request GET 'http://localhost:8080/customer/api/v1/health'

It returns the following response:

< {"status":"UP"}

To shut the Docker container, use docker stop and the container ID, for example:

docker stop c1c3925595047ff5744507dd0abc05b1063f7dc884c3e2a4c9864633a2780d2b

Conclusion

In this part of our series on building Java microservices, we learned how to containerize our Spring Boot application using Docker. In the next part, we will take advantage of Amazon Web Services, which is the number one public cloud provider with a 32% market share, and learn how to deploy Docker containers into the cloud. See you soon!

posts
Alpaquita vs Alpine: a head-to-head comparison
figure
Nov 10, 2022
Dmitry Chuyko
shorts
Critical vulnerabilities in OpenSSL 3.0
Nov 11, 2022
Sergey Chernyshev

Find out about the newest CVEs discovered in OpenSSL 3.0 and how to eliminate the risk of exploits

Subcribe to our newsletter

figure

Read the industry news, receive solutions to your problems, and find the ways to save money.