Running a Spring Boot application with Docker

In this tutorial we will learn how to run a Spring Boot application using Docker using two different approaches: by setting up a Dockerfile and using a configuration option of Spring Boot Maven plugin.

Hard requirements

  • A JDK 1.8 or newer to build your Spring Boot application
  • A Docker environment on your Machine. As an alternative, you can consider using Podman.

For the purpose of this example, we will use the Spring Boot Command Line interface. You can choose any other option to bootstrap your Spring Boot project.

Create a simple Spring Boot REST Project

Firstly, create a new project which includes the web dependencies:

spring init -dweb demo-rest

Now import the Maven project in your favourite IDE and add a model class named Customer that will be returned by a GET Request:

package com.example.demorest;

public class Customer {
  private int id;
  private String name;

  public Customer(int id, String name) {
    super();
    this.id = id;
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }
}

All you need to build a Rest Service in Spring Boot is a RestController:

package com.example.demorest;

import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomerController {
  @RequestMapping("/")
  public List<Customer> findAll() {
    List<Customer> customerList = new ArrayList<Customer>();
    customerList.add(new Customer(1, "frank"));
    customerList.add(new Customer(2, "john"));
    return customerList;
  }
}

RestController : The @RestController annotation provides a combination of @ResponseBody and @Controller annotations. This is a standrd option to create REST Controllers.

RequestMapping: The method with @RequestMapping would handle a generic request to the “/” URI. If not specified, it maps a GET Request.

Now compile and package the application with:

$ mvn clean install

Let’s check the two available approaches for building a Docker image of our example application

Option #1 Create a Dockerfile

Firstly, create a file Dockerfile in the project root folder with the following content:

FROM adoptopenjdk/openjdk11:alpine-jre
# Add Maintainer Info
LABEL maintainer="marchioni.francesco@gmail.com"

# Add a volume pointing to /tmp
VOLUME /tmp

# Make port 8080 available to the world outside this container
EXPOSE 8080

# The application's jar file
ARG JAR_FILE=target/demo-docker-0.0.1-SNAPSHOT.jar

# Add the application's jar to the container
ADD ${JAR_FILE} demo-docker-0.0.1-SNAPSHOT.jar

# Run the jar file
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/demo-docker-0.0.1-SNAPSHOT.jar"]

This Dockerfile is quite simple: let’s review it:

  • FROM: this is the base Image we will use: adoptopenjdk/openjdk11:alpine-jre. If you prefer using JDK 8, switch to openjdk:8-jdk-alpine image as base image.
  • VOLUME: Volumes allow to persist data generated by the container on the Host, and share directories from the Host OS with the container.The VOLUME instruction creates a mount point on the container with the specified path. When you run the container, you can specify the directory on the Hot OS to which the given mount point will be mapped to. After that, anything that the container writes to the mounted path is written to the mapped directory on the Host OS.In the above Dockerfile, we created a mount point with path /tmp because this is where the spring boot application creates working directories for Tomcat by default.
  • EXPOSE: This instruction allows you to expose a certain port to the outside world.
  • ARG: The ARG instruction defines a variable with a default value. You can override the default value of the variable by passing it at build time.
    ARG <name>[=<default value>] 
  • ADD: The ADD instruction allows to copy new files and directories to the docker image.
  • ENTRYPOINT: This is the application entrypoint that is executed inside the container.

Save the Dockerfile in the current directory. Then, we will build and tag the application with:

docker build -t docker-demo .

Finally, you can run it with:

docker run -p 8080:8080 docker-demo

The application will start on port 8080:

The source code for this example is available here: https://github.com/fmarchioni/masterspringboot/tree/master/demo-docker

Option #2 Use Spring Boot Maven plugin

This option does not require creating any other file. All you need, is adding to the spring-boot-maven-plugin a configuration option for image:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <image>
      <name>pedroluiznogueira/${project.artifactId}:${project.version}</name>
    </image>
    <pullPolicy>IF_NOT_PRESENT</pullPolicy>
  </configuration>
</plugin>

You can also specify a pullPolicy: acceptable values are ALWAYS, NEVER, and IF_NOT_PRESENT.

Next, to build it, you run:

mvn spring-boot:build-image

if you check the list of available Docker images, you will see that a new one is available:

$ docker images
REPOSITORY                                    TAG           IMAGE ID       CREATED          SIZE
docker-demo                                   latest        e861294b2bee   17 minutes ago   166MB
. . . .
pedroluiznogueira/pom-example                 0.0.3         d546b71161e4   42 years ago     275MB

Finally, run the Image as follows:

docker run -p 8080:8080 docker.io/pedroluiznogueira/pom-example:0.0.3

The Application will start:

Great! We just managed to run our first Spring Boot application on Docker!

The Source code for the second example is available here: https://github.com/pedroluiznogueira/docker-pom-example

Credits to the Java Software Engineer Pedro Luiz for sharing this example.

Keep learning Spring Boot and Containers

If you want to learn how to get your Dockerfile and image automatically created for you, then check this tutorial: How to build Docker images of your Spring Boot applications

If you want to learn how to deploy your Spring boot application on OpenShift check : How to run a Spring Boot application on Openshift.