How to dockerize Spring Boot app?

Read Time:4 Minute, 15 Second

Today I’m going to show you how to merge the power of containers implemented by Docker and Spring Boot application.

I’m going to use app from one of my previous articles – https://rocketzki.com/index.php/2019/07/21/creating-spring-boot-app-with-persisted-login-and-thymeleaf-templates-how-to/. I will show you how to create docker image so our app can be deployed easily using containers.

First of all we need to install Docker on our PC. https://www.docker.com/ – you need to create account on the website and download docker for desktop. After installation we need to download project from git: https://github.com/rocketzki/boot-persisted-thymeleaf

We need to edit build.gradle file. I have used gradle plugin which is great assistance when building docker image from gradle project.

build.gradle

buildscript{
    dependencies{
        classpath 'gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0'
    }
}
plugins {
    id 'java'
    id 'com.palantir.docker' version '0.22.1'
    id 'org.springframework.boot' version '2.2.0.RELEASE'
}

group 'how-tos'
version '2.0'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '2.1.5.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.1.5.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.1.5.RELEASE'
    compile group: 'com.h2database', name: 'h2', version: '1.4.199'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf', version: '2.1.6.RELEASE'
    compile group: 'org.thymeleaf.extras', name: 'thymeleaf-extras-springsecurity5', version: '3.0.4.RELEASE'

}


configurations {
    jar.archiveName = 'boot-persisted-thymeleaf.jar'
}


task unpack(type: Copy) {
    dependsOn bootJar
    from(zipTree(tasks.bootJar.outputs.files.singleFile))
    into("build/dependency")
}

docker {
    name "${project.group}/${bootJar.baseName}"
    copySpec.from(tasks.unpack.outputs).into("dependency")
    buildArgs(['DEPENDENCY': "dependency"])
}

Firstly, we need to add a dependency to the buildscript so that we can use the gradle docker plugin. Then we add

id ‘com.palantir.docker’ version ‘0.22.1’
id ‘org.springframework.boot’ version ‘2.2.0.RELEASE’

to add dependency to the plugin itself.

At the end we add unpack task for unpacking fat jar (jar created by bootJar task) which copies all files with libraries to the build/dependency folder.

Then we need to configure the docker gradle task. I will set the name for the image – it is set up from the jar file properties , copy dependencies from the dependency folder (to which we have copied libraries using unpack task), point that the application with its dependencies (DEPENDENCY variable passed as a build argument) is located at dependency folder.

Ok so now we have gradle project set up for dockerization. We need to write a core file which describes docker image creation – Dockerfile.

Dockerfile

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=build/dependency
COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY ${DEPENDENCY}/META-INF /app/META-INF
COPY ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.rocketzki.persistedthymeleaf.TheApp"]
EXPOSE 8080

Dockerfile contains instructions for the docker image building process. Each instruction creates immutable layer is put on the top of the previous one. More info on that builder can fe found: https://docs.docker.com/engine/reference/builder/

As a base image I have used Alpine linux distro with openjdk 8. The volume mounted at/tmp is added because Spring Boot application creates working directories for Tomcat in that folder by default. Then I am addin a variable DEPENDENCY pointing to the folder with unpacjet fatJar (done by unpack task describe previously). In the next step I copy BOOT-INF/lib directory with dependency libs, and a BOOT-INF/classes directory with the application classes itself.

ENTRYPOINT instruction runs the main application class by default when the container starts.

Last instruction tells docker builder to open port 8080 on the container. The Spring Boot application is set by default to serve content on that port.

All we need to do now is to run the docker image building process! Open terminal in you InteliJ (or Eclipse) being in the project directory and type: gradle docker (the Docker Desktop applicaiton must be running!).

Once the process is finished you can type: docker images to check if it has been created.

REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
how-tos/boot-persisted-thymeleaf   latest              9eb948dc2677        6 hours ago         147MB

To run the application type: docker run -p 8080:8080 how-tos/boot-persisted-thymeleaf

The appliction starts up and is ready do run at: localhost:8080

The -p 8080:8080 flag binds port 8080 on the host machine to the port 8080 on the container (under which the app is served – HOST_PORT:CONTAINER_PORT).

Application starts quickly and works reliably.

I have showed you how to quickly move our Spring Boot app to Docker image and how to run it using gradle and Docker of course. See you round!

Should you have any questions, don’t hesitate to reach me via linkedin, facebook, email or via comments.

Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
0 0 votes
Article Rating
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Jannik
Jannik
8 months ago

That’s a good one! Thanks

1
0
Would love your thoughts, please comment.x
()
x