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.
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
- Building your first Java Spring Boot web app
- Running and building your application without Docker, first
- 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:
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.
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:
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:
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.
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:
Here’s the console for the ongoing build. You’ll see that STS has successfully built our JAR:
You can access this JAR file in the Target folder shown below:
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:
- Creating a
Dockerfile
- Building the Docker image
- 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 yourDockerfile
uses to build a new image. We’re usingeclipse-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 destinationEXPOSE
– Reveals specific ports to the host machine. We’re exposingport 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:
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
Access your application at http://localhost:8080/DockerProducts. Here’s a quick glimpse of our webpage!
You can also view your image and running container via the Docker Dashboard:
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"