How I Built My First Containerized Java Web Application

It gives me immense pleasure to present this blog as I intern with Docker as a Product Marketer. This incredible experience has given me the chance to brainstorm many new ideas. As a prior Java developer, I’ve always been amazed by how Java and Spring Boot work wonders together! Shoutout to everyone who helped drive the completion of this blog!

 

For the past 30 years, web development has become vital across multiple industries. Developers have long used Java and the Spring Framework for web development, particularly on the server side.

Java follows the “old is gold” philosophy. And after evolving over 25 years, it’s still one of today’s most popular programming languages. Fifty-million websites including Google, LinkedIn, eBay, Amazon, and Stack Overflow, use Java extensively.

 

Java meets docker

In this blog, we’ll create a simple Java Spring Boot web application and containerize it using Docker, which works by running our application as a software “image.” This image packages together the operating system, code, and any supporting libraries or dependencies. This makes it much easier to develop and deploy cross-platform applications. Let’s jump into the process.

Here’s what you’ll be doing

  1. Building your first Java Spring Boot web app
  2. Running and building your application without Docker, first
  3. Containerizing the Spring Boot web application

What you’ll need

1. JDK 17 or above
2. Spring Tool Suite for Eclipse
3. Docker Desktop

Building your first Java Spring Boot web app

We’re using Spring Tool Suite (STS) for our application. STS is Eclipse-based and tailored for creating Spring applications. It includes a built-in and customizable Tomcat server that offers Spring configuration file validation, coding assistance, and more.

Another advantage is that Spring Tool Suite 4 doesn’t need an explicit Maven plugin. It ships with its own Maven plugin, which is easy to enable by navigating to Windows > Preferences > Maven. This IDE also offers an approachable UI and tools to simplify Spring app development.

That said, let’s now create a new base project for our app. Create a new Spring starter project from the Package Explorer:

 

Spring starter

Spring start webapp

Since we’re building a Spring web app, we need to add our Spring web and Thymeleaf dependencies. Thymeleaf is a Java template engine for implementing frontend functions like HTML, XML, JavaScript, CSS, or even plain text files with Spring Boot.

Starter project dependencies

You’ll notice that configuring your starter project takes some time, since we’re pulling from the official website. Once finished, you can further configure your project base. The project structure looks like this:

Project structure

By default, Maven compiles sources from src/main/java and src/test/java is where your test cases reside. Meanwhile, src/main/resources is the standard Maven location for application resources like templates, images and other configurations.

Maven’s fundamental unit of work is the pom.xml (Project Object Model). It contains information about the project, its dependencies, and configuration details that Maven uses while building.

Here’s our project’s POM. You’ll also notice the Spring Web and Thymeleaf dependencies that we added initially:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>webapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>webapp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

 

Next, if you inspect the source code inside src/main/java, you’ll see a generated class WebappApplication.java file:

package com.example.mypkg;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebappApplication {

public static void main(String[] args) {
SpringApplication.run(WebappApplication.class, args);
}

}

 

This is the main class that your Spring Boot app executes from. The @SpringBootApplication annotation denotes a variety of features — including the ability to enable Spring Boot auto-configuration, Java-based Spring configuration, and component scanning.

Therefore, @SpringBootApplication is akin to using @Configuration@EnableAutoConfiguration, and @ComponentScan with their default attributes. Here’s more information about each annotation:

    • @Configuration denotes that the particular class has @Bean definition methods. The Spring container may process it to provide bean definitions.
    • @EnableAutoConfiguration helps you auto-configure beans present in the classpath.
    • @ComponentScan lets Spring scan for configurations, controllers, services, and other predefined components.

A Spring application is bootstrapped as a standalone from the main method using SpringApplication.run(<Classname>.class, args).

As mentioned, you can embed both static and dynamic web pages in src/main/resources. Here, we’ve designated Products.html as the home page of our application:

Products html

We’ll use a simple RESTful web service to grab our application’s home page. First, create a Controller class in the same location as your main class. This’ll be responsible for processing incoming REST API calls, preparing a model, and returning the rendered view as a response.

package com.example.mypkg;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

@GetMapping(value = "/DockerProducts")
public String index() {
return "Products";
}

}

 

The @Controller annotation assigns the controller role to a particular class. You’d use this annotation to mark a class as a web request handler. @GetMapping commonly maps HTTP GET requests onto specific handler methods. Here, it’s the method “index” that returns our app’s homepage, called “Products.”

Building and running the application without Docker

It’s time to test our application by running it as a Spring Boot application. 

 

Spring boot stencil

Your application is now available at port 8080, which you can access by opening http://localhost:8080/DockerProducts in your browser.

We’ve tested our project by running it. It’s now time to build our application by  creating a JAR file. Choose the “Maven clean” install option within Spring Tool Suite:

 

Maven clean

 

Maven install

Here’s the console for the ongoing build. You’ll see that STS has successfully built our JAR:

Jar build success

You can access this JAR file in the Target folder shown below:

Jar target file

Containerizing our Spring Boot web application with Docker

Next, we’re using Docker to containerize our application. Before starting, download and install Docker Desktop. Docker Desktop includes multiple developer-focused tools like the Docker CLI, Docker Compose, and Docker Engine. It also features a user-friendly UI (the Docker Dashboard) that streamlines common container, image, and volume management tasks.

Once that’s installed, we’ll tackle containerization with the following steps:

  1. Creating a Dockerfile
  2. Building the Docker image
  3. Running Docker container to access the application

Creating a Dockerfile

A Dockerfile is a plain-text file that specifies instructions for building a Docker image. You can create this in your project’s root directory:

FROM eclipse-temurin:17-jdk-focal
ADD target/webapp-0.0.1-SNAPSHOT.jar webapp-0.0.1-SNAPSHOT.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "webapp-0.0.1-SNAPSHOT.jar"]

 

What does each instruction do?

  • FROM – Specifies the base image that your Dockerfile uses to build a new image. We’re using eclipse-temurin:17-jdk-focal as our base image. The Eclipse Temurin Project shares code and procedures that enable you to easily create Java SE runtime binaries. It also helps you leverage common, related technologies that appear throughout Java’s ecosystem.
  • ADD – Copies the new files and JAR into your Docker container’s filesystem at a specific destination
  • EXPOSE – Reveals specific ports to the host machine. We’re exposing port 8080 since embedded Tomcat servers automatically use it.
  • ENTRYPOINT – Sets executables that’ll run once the container spins up

Building the Docker image

Docker images are instructive templates for creating Docker containers. You’ll build your Docker image by opening the STS terminal at your project’s root directory, and entering the following command:

docker build -t docker_desktop_page .

 

Our image name is docker_desktop_page. Here’s how your images will appear if you request a list:

 

Images list

Run your application as a Docker container

A Docker container is a running instance of a Docker image. It’s a lightweight, standalone, executable software package that includes everything needed to run an application. Enter this command to start your container:

docker run -p 8080:8080 docker_desktop_page

Spring bw output

Access your application at http://localhost:8080/DockerProducts. Here’s a quick glimpse of our webpage!

Final webpage

You can also view your image and running container via the Docker Dashboard:

Dd image

Dd container

You can also manage these containers within the Container interface.

Containerization enables easier build and deploy

Congratulations! You’ve successfully built your first Java website. You can access the full project source code here.

You’ve now learned how easy containerizing an application is — even without prior Docker experience. To learn more about developing your next Java Spring Boot application, check out our Getting started with Java Overview.

Feedback

0 thoughts on "How I Built My First Containerized Java Web Application"