Why Spring Boot is so popular?
Spring Boot is a framework that makes it easy to create stand-alone, production-grade Spring applications. It provides a number of features that make it easy to get started, such as auto-configuration and embedded web servers.
Spring Boot is popular in container environments because it makes it easy to create applications that can be run in containers. Spring Boot provides a number of features that make it easy to configure applications for running in containers, such as support for Docker and Kubernetes.
In addition, Spring Boot is a very popular framework, so there is a large community of developers who are familiar with it and can help you if you need it.
We shall use plain vanilla Docker to containerize a sample Spring Boot application.
About the application
Creating a Spring Boot project step-by-step is not the scope of this post. It is a simple Spring Boot web application with only one controller and only one request handler. This shown below.
package com.sredigest.docker;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/")
public String index() {
return "Greetings from Spring REST Controller";
}
}
We shall containerize it in 3 steps.
- Add a Dockerfile
- Build docker image
- Run Docker container
Step 1: Dockerfile creation
A Dockerfile is a text document that contains a set of instructions for building a Docker image. A Dockerfile is used to create a Docker image by specifying the image’s contents, such as the operating system, packages, and applications. Once a Dockerfile has been created, it can be used to build an image by using the docker build command.
This is usually generated in the root folder of the project folder. You may right click on your project name and select New > Untitled Text File. Save it as Dockerfile (one word with upper case D)
The file has the following content.
This is the contents of the Dockerfile used in this project.
FROM openjdk:17
EXPOSE 8080
ARG JAR_FILE=target/docker-test-1.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
Line 1: It says to make openjdk 17 available in the container
Line 2: It asks the container to expose port 8080 for client to access
Line3: It declare a variable JAR_FILE which points at the output jar file of this Spring Boot project. You may have to replace it with the file name of your project.
Line 4: Copies the output of the Spring Boot into the container as app.jar
Line 5: The ENTRYPOINT instruction specifies the command that is executed when a container is run. It can be a single command or a list of commands.
Step 2: Build a Docker image
Ensure docker is installed on your Linux VM. If not, you may follow this post. Docker installation on Linux. I am not fond of running Docker in Windows. It has numerous dependencies. Still, I tried to provide the steps on Windows at the end of this post.
Login to Linux server as docker user.
# sudo su - docker
$ cd $HOME
Create a directory to copy the Dockerfile
$ mkdir docker-spring-test
$ cd docker-spring-test/
Create a directory target to copy the jar file.
$ mkdir target
Now, use SCP or FTP tools to copy the Dockerfile and jar file to docker-spring-test directory and target directories respectively. Issue the command to build the docker image. Based on your server speed and internet speed, it will take some time to complete.
$ docker build -t sredigest/docker- spring-test .
[+] Building 247.9s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.4s
=> => transferring dockerfile: 225B 0.0s
=> [internal] load metadata for docker.io/library/openjdk:17 4.1s
=> [internal] load .dockerignore 0.4s
=> => transferring context: 2B 0.0s
=> [internal] load build context 0.9s
=> => transferring context: 19.71MB 0.1s
=> [1/2] FROM docker.io/library/openjdk:17@sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8 143.5s
=> => resolve docker.io/library/openjdk:17@sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8 0.6s
=> => sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8 1.04kB / 1.04kB 0.0s
=> => sha256:98f0304b3a3b7c12ce641177a99d1f3be56f532473a528fda38d53d519cafb13 954B / 954B 0.0s
=> => sha256:5e28ba2b4cdb3a7c3bd0ee2e635a5f6481682b77eabf8b51a17ea8bfe1c05697 4.45kB / 4.45kB 0.0s
=> => sha256:38a980f2cc8accf69c23deae6743d42a87eb34a54f02396f3fcfd7c2d06e2c5b 42.11MB / 42.11MB 16.7s
=> => sha256:de849f1cfbe60b1c06a1db83a3129ab0ea397c4852b98e3e4300b12ee57ba111 13.53MB / 13.53MB 22.2s
=> => sha256:a7203ca35e75e068651c9907d659adc721dba823441b78639fde66fc988f042f 187.53MB / 187.53MB 124.8s
=> => extracting sha256:38a980f2cc8accf69c23deae6743d42a87eb34a54f02396f3fcfd7c2d06e2c5b 1.9s
=> => extracting sha256:de849f1cfbe60b1c06a1db83a3129ab0ea397c4852b98e3e4300b12ee57ba111 0.5s
=> => extracting sha256:a7203ca35e75e068651c9907d659adc721dba823441b78639fde66fc988f042f 3.8s
=> [2/2] ADD target/docker-test-1.jar app.jar 98.0s
=> exporting to image 0.5s
=> => exporting layers 0.4s
=> => writing image sha256:e4c747f89a691455dbea2c56ee4136599b50a461d10991e3024a1d0298da500e 0.0s
=> => naming to docker.io/sredigest/docker-spring-test
Image creation is successful. Let’s check using ls command.
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
sredigest/docker-spring-test latest e4c747f89a69 2 minutes ago 491MB
myorg/myapp latest 7bbeea427bd7 23 hours ago 335MB
hello-world latest d2c94e258dcb 9 months ago 13.3kB
sredigest/docker-spring-test is our app name. As it successfully created, let’s run a container using this image.
$ docker run -p 8080:8080 sredigest/docker-spring-test
-p 8080:8080 maps the host 8080 port to container’s 8080 port. The application is started now.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.2)
2024-02-12T05:12:51.879Z INFO 1 --- [ main] c.s.docker.DockerSpringTestApplication : Starting DockerSpringTestApplication v1 using Java 17.0.2 with PID 1 (/app.jar started by root in /)
2024-02-12T05:12:51.884Z INFO 1 --- [ main] c.s.docker.DockerSpringTestApplication : No active profile set, falling back to 1 default profile: "default"
2024-02-12T05:12:52.875Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-02-12T05:12:52.886Z INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-02-12T05:12:52.886Z INFO 1 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.18]
2024-02-12T05:12:52.925Z INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-02-12T05:12:52.927Z INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 920 ms
2024-02-12T05:12:53.268Z INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path ''
2024-02-12T05:12:53.282Z INFO 1 --- [ main] c.s.docker.DockerSpringTestApplication : Started DockerSpringTestApplication in 1.859 seconds (process running for 2.319)
Let’s try to access the application from the Linux host VM. We got the response.
# curl http://localhost:8080
Greetings from Spring REST Controller
The request goes to 8080 port of the Linux host.
It is getting forwarded to 8080 port of the container.
Container’s port is bound by Spring Boot application.
The incoming request is handled by the HelloController class and its index() method.
Try this in your environment.
Creating Docker image in Windows O/S
You need a Windows Enterprise or Pro edition of Windows or any Server Windows Operating System. (You know now why Windows is not popular in Container environment!)
Install Docker Desktop (Usually it is installed C:\Program Files\docker folder)
Open a cmd using run as administrator and run docker demon.
cd "C:\Program Files\Docker\Docker\resources"
dockerd.exe
time="2024-02-12T12:12:17.275112900+08:00" level=info msg="Starting up"
time="2024-02-12T12:12:17.327113600+08:00" level=info msg="Windows default isolation mode: hyperv"
time="2024-02-12T12:12:17.351114000+08:00" level=info msg="[graphdriver] trying configured driver: windowsfilter"
time="2024-02-12T12:12:17.360719800+08:00" level=info msg="Loading containers: start."
time="2024-02-12T12:12:17.361759700+08:00" level=info msg="Restoring existing overlay networks from HNS into docker"
time="2024-02-12T12:12:19.542528400+08:00" level=info msg="Loading containers: done."
time="2024-02-12T12:12:21.523523400+08:00" level=info msg="Docker daemon" commit=fce6e0c containerd-snapshotter=false storage-driver=windowsfilter version=25.0.2
time="2024-02-12T12:12:21.529503400+08:00" level=info msg="Daemon has completed initialization"
time="2024-02-12T12:12:21.579702600+08:00" level=info msg="API listen on //./pipe/docker_engine"
Run another elevated cmd (Run as administrator)
run as administrator. Go to the workspace project directory of eclise IDE
cd "C:\common_place\aggregator\docker-spring-test"
Build the docker image.
docker build -t sredigest/docker-spring-test .
Sending build context to Docker daemon 19.88MB
Step 1/5 : FROM openjdk:17
17: Pulling from library/openjdk
4612f6d0b889: Pull complete
ba8181afd426: Pull complete
ba1c113303b8: Pull complete
e25b7048e3be: Pull complete
c883299a3cef: Pull complete
9ada7b0f3e19: Pull complete
21e2635b06d6: Pull complete
8813106cd5a2: Pull complete
8653875d64d5: Pull complete
b8a615716567: Pull complete
61abf1e1d7b5: Pull complete
Digest: sha256:528707081fdb9562eb819128a9f85ae7fe000e2fbaeaf9f87662e7b3f38cb7d8
Status: Downloaded newer image for openjdk:17
---> 2b6a219778b6
Step 2/5 : EXPOSE 8080
---> Running in 10880f12c542
---> Removed intermediate container 10880f12c542
---> 1cb3cacb1afc
Step 3/5 : ARG JAR_FILE=target/docker-test-1.jar
---> Running in 55363c41f59c
---> Removed intermediate container 55363c41f59c
---> 88dec3ad2951
Step 4/5 : ADD ${JAR_FILE} app.jar
---> 4ad1274186ae
Step 5/5 : ENTRYPOINT ["java", "-jar", "/app.jar"]
---> Running in 9b21ea297c93
---> Removed intermediate container 9b21ea297c93
---> ca912cd37152
Successfully built ca912cd37152
Successfully tagged sredigest/docker-spring-test:latest
What's Next?
View a summary of image vulnerabilities and recommendations → docker scout quickview
Image is created successfully. Let’s verify using ls command.
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
sredigest/docker-spring-test latest ca912cd37152 4 minutes ago 6.1GB
openjdk 17 2b6a219778b6 22 months ago 6.08GB
The image is created. But I couldn’t run it as my Windows home O/s is not supportive. If you have a supported windows platform, you may run it using the same command, used in Linux O/s.
—
This post is written as part of #WriteAPageADay campaign of BlogChatter