How to create a microservice with Spring Boot and Docker

We will learn how to run a Spring Boot microservice inside a Docker container

In a previous post we learned how to install Docker and how to run a Java Hello Word inside the Docker container. Now we will learn how to run a Spring Boot microservice application within Docker.

Spring Boot Docker

Minimum dependencies of a Spring Boot microservice

The first thing we are going to do is define the dependencies we need. Spring Boot requires at least these dependencies:

org.springframework.boot:spring-boot-starter-web
org.springframework.boot:spring-boot-starter-test

The configuration for Gradle of these dependencies is:

plugins {
	id 'org.springframework.boot' version '2.1.9.RELEASE'
	id 'io.spring.dependency-management' version '1.0.8.RELEASE'
	id 'java'
}

group = 'com.gustavopeiretti'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

The configuration for Maven of these dependencies for Spring Boot:

<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.1.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.gustavopeiretti</groupId>
	<artifactId>springbootdocker</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springbootdocker</name>
	<description>Demo project for Spring Boot with Docker</description>

	<properties>
		<java.version>1.8</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>
	</dependencies>

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

</project>

Create the Spring Boot microservice

You must create the main class that Spring will start. We annotate the class with @SpringBootApplication.
The @SpringBootApplication annotation is equivalent to using @Configuration + @EnableAutoConfiguration + @ComponentScan with its default attributes.
Check out this other post for more details about the main class

@SpringBootApplication
public class SpringbootdockerApplication {

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

}

Then create a ‘rest controller’ that you annotate with RestController.
Create a Home class and annotate the method with RequestMapping.
The home method below maps the base path of your services.
You can read more about RestController

@RestController
public class Home {

    @RequestMapping("/")
    public String home() {
        return "Hello Spring Boot with Docker";
    }

}

.
You can run the application from the console.

  • If you use gradle gradle bootRun
  • If you use maven mvn spring-boot:run
  • If you use the gradle wrapper ./gradlew bootRun

This is the console for ./gradlew bootRun Spring Boot Docker

Open the URL localhost:8080. Spring Boot Docker

Finish the execution of SpringBoot with Gradle by pressing Ctrl + C. If you cannot finish gradlew when you press ctrl + c, you will have to open another console and run ./gradlew -stop

Spring Boot Docker

Build your Spring Boot application

Before continuing with the other steps, be sure to make a build of the project to make available the jar file that we will need later.

with gradle

Gradle leaves the jar in the \build\libs folder of your project with the name you have in the settings.gradle file.

gradlew build Spring Boot Docker

Gradle create jar file with the name you have specified in the settings.gradle file. Spring Boot Docker

with maven

Maven leave the jar in the \target folder of your project with the name you have defined in the artifactId tag of your pom.xml file

mvnw package Spring Boot Docker

Create a Docker file to run SpringBoot

ok, you already have your service application running.
Now, You will start configuring Docker so that your service runs there.
To create the Docker configuration for SpringBoot, create a Dockerfile text file with these instructions:

FROM openjdk:8-jdk-alpine
VOLUME /tmp
EXPOSE 8080
ARG JAR_FILE=build/libs/springbootdocker-0.0.1-SNAPSHOT.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

FROM: Note that in the first line you use a docker image that is already armed with linux and java 8. That is, our service will run on a linux and Java 8 system.

ADD: The ADD instruction copies our application into Docker.
Our gradle or maven config leaves the file jar with the name “springbootdocker-0.0.1-SNAPSHOT.jar”.
This springbootdocker-0.0.1-SNAPSHOT.jar file is added to the container with the instruction ADD with the name app.jar
If the path of your jar application is elsewhere, you must modify it with the correct route. In the event that you have created your app with maven, you must use the path of the maven target.

ENTRYPOINT: Then we execute the file when starting docker with the instruction ENTRYPOINT

Spring Boot Docker

Once the Dockerfile file is defined, you run docker build. The -t parameter defines the name that we will give to the container and that we will use later to execute it.

 docker build -t springbootdockerexample .

Look in the console with what happens with your Docker config you created.
In each step you see that the linux image with java 8 (FROM) is created, after port 8080 is exposed from the container to the container host (EXPOSE), the jar (ADD) is copied and executed (ENTRYPOINT) .

Spring Boot Docker

After the build of the docker is finished, you can execute it with the name you gave it.

Running Docker with Spring Boot

With the docker image ready, you can now run it with docker run The -p parameter tells Docker to expose port 8080 of our application that is running inside the container, on port 5000 of the operating system.

docker run  -p 5000:8080 springbootdockerexample

Spring Boot Docker

Now you open the URL pointing to the port you told docker. In this case 5000 http://localhost:5000/

Smile your application is working in a Docker container! Spring Boot Docker

Create the Docker image with Spring Boot using Gradle

If you use Gradle you can add a plugin to build the image and execute it directly from the Gradle commands. For this, you have to modify the build.gradle file by adding this plugin https://github.com/palantir/gradle-docker

The new thing you add is what you see in buildscript, then the apply of the plugin and finally a new task docker.

// docker: new plugin 
buildscript {
	dependencies {
		classpath "gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.22.1"
	}
}

plugins {
	id 'org.springframework.boot' version '2.1.9.RELEASE'
	id 'io.spring.dependency-management' version '1.0.8.RELEASE'
	id 'java'
}

group = 'com.gustavopeiretti'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

// docker: plugin apply  
apply plugin: 'com.palantir.docker'

// docker: new task docker 
docker {
    dependsOn build
    name "${project.name}"
    files bootJar.archivePath
    buildArgs(['JAR_FILE': "${bootJar.archiveName}"])
}

Let’s analyze the new docker task of the gradlew build file that we have modified:

  • dependsOn build we tell you that this task depends on the build of gradle
  • name “${project.name}” will be the name of the container, we will give you the name of the project that we have in settings.gradle
  • files bootJar.archivePath will make the jar file generated by the build available
  • buildArgs ([‘JAR_FILE’: “$ {bootJar.archiveName}"]) sends as an argument the name of the jar file.

Spring Boot Docker

Running the Docker image with Spring Boot using Gradle

If you have already modified your build file by adding the com.palantir.docker plugin, you can directly execute the build and create your image from gradle.
From your console, you will use gradlew build docker to build an image

gradlew build docker
docker run -p 5000:8080 springbootdocker

Spring Boot Docker

Create the Docker image with Spring Boot using Maven

In the case of using Maven, you must add this plugin if you want to create the image directly from mvn https://github.com/spotify/dockerfile-maven

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.9</version>
                <configuration>
                    <repository>${project.artifactId}</repository>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
                <executions>
                    <execution>
                        <id>default</id>
                        <phase>install</phase>
                        <goals>
                            <goal>build</goal>
                            <goal>push</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Your full pom.xml looks like this:

<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.1.9.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gustavopeiretti</groupId>
    <artifactId>springbootdocker</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springbootdocker</name>
    <description>Demo project for Spring Boot with Docker</description>

    <properties>
        <java.version>1.8</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>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.13</version>
                <configuration>
                    <repository>${project.artifactId}</repository>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
                <executions>
                    <execution>
                        <id>default</id>
                        <goals>
                            <goal>build</goal>
                            <goal>push</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Running the Docker image with Spring Boot using Maven

Once you have added the https://github.com/spotify/dockerfile-maven plugin you run:

mvnw dockerfile:build
docker run -p 5000:8080 springbootdocker

Spring Boot Docker

When you execute docker run your app will remain in the url localhost:5000

Spring Boot Docker

A summary of the docker commands that were useful in this post:

  • docker build to create the docker image
  • docker run to run the docker image
  • docker images see the docker images you have available.

As always this code can be found by GitHub

https://github.com/gustavopeiretti/spring-boot-examples/tree/master/spring-boot-docker-example

Conclusion

You learned how to create a Spring Boot Rest application, configure a dockerfile for your application, build your Docker container and run your microservice from the container. You also learned some basic docker commands.

Hi! If you find my posts helpful, please support me by inviting me for a coffee :)

See also