In this blog we will learn more about Containerization. With the help of working example we will learn; How to build a REST API using @RestController annotation. How to Create Docker Image, Deploy and Run the Docker Image in Local.
spring boot rest controller example with docker image build deploy and run – spring boot rest api docker example
We need to update Docker Desktop Setting as below
First of all we will build a Spring Boot based REST API (spring-boot-docker), add docker specific configuration and then we will create the docker image.
In this application, we exposed a REST API @RequestMapping("/echo/{name}")
, which will respond with name message to the client
Java 8
Docker Desktop
Spring Boot 2.4.4
Eclipse/Red Hat JBoss Developer Studio 11.3.0.GA
High level application structure would be looked like as below.
package com.the.basic.tech.info.echo;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class EcoApplication {
public static void main(String[] args) {
SpringApplication.run(EcoApplication.class, args);
}
}
@RestController
class EchoRestController {
private static final Logger logger = LoggerFactory.getLogger(EchoRestController.class);
@RequestMapping("/echo/{name}")
public String echoDocker(@PathVariable(value = "name") String name) {
String response = "Echo " + name + " Response received on : " + new Date();
logger.info("Response :: {}", response);
return response;
}
}
Pom.xml file would be looked like as below. Two plugins, dockerfile-maven-plugin
and maven-dependency-plugin
need to be added.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.the.basic.tech.info</groupId>
<artifactId>spring-boot-docker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-docker</name>
<description>Demo project for Spring Boot Containerization</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<docker.image.prefix>spring-boot-docker</docker.image.prefix>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<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>junit</groupId>
<artifactId>junit</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.7</version>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/spring-boot-docker-0.0.1-SNAPSHOT.jar spring-boot-docker-app.jar
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /spring-boot-docker-app.jar" ]
server port we can update here, otherwise default port 8080 will be considered.
server.port = 9080
[INFO] Image will be built as spring-boot-docker/spring-boot-docker:latest
[INFO]
[INFO] Step 1/5 : FROM openjdk:8-jdk-alpine
[INFO]
[INFO] Pulling from library/openjdk
[INFO] Digest: sha256:94792824df2df33402f201713f932b58cb9de94a0cd524164a0f2283343547b3
[INFO] Status: Image is up to date for openjdk:8-jdk-alpine
[INFO] ---> a3562aa0b991
[INFO] Step 2/5 : VOLUME /tmp
[INFO]
[INFO] ---> Using cache
[INFO] ---> 641d4242f87d
[INFO] Step 3/5 : ADD target/spring-boot-docker-0.0.1-SNAPSHOT.jar spring-boot-docker-app.jar
[INFO]
[INFO] ---> 4e487d7fc055
[INFO] Step 4/5 : ENV JAVA_OPTS=""
[INFO]
[INFO] ---> Running in 7f4a3dab2932
[INFO] Removing intermediate container 7f4a3dab2932
[INFO] ---> 22f106d5b853
[INFO] Step 5/5 : ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /spring-boot-docker-app.jar" ]
[INFO]
[INFO] ---> Running in 458fab94eeea
[INFO] Removing intermediate container 458fab94eeea
[INFO] ---> f33cb2483029
[INFO] Successfully built f33cb2483029
[INFO] Successfully tagged spring-boot-docker/spring-boot-docker:latest
[INFO]
[INFO] Detected build of image with id f33cb2483029
[INFO] Building jar: C:\Users\spring-boot-docker\target\spring-boot-docker-0.0.1-SNAPSHOT-docker-info.jar
[INFO] Successfully built spring-boot-docker/spring-boot-docker:latest
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 50.961 s
[INFO] Finished at: 2021-06-10T15:37:29+05:30
[INFO] Final Memory: 53M/367M
[INFO] ------------------------------------------------------------------------
C:\Users\spring-boot-docker>docker run -p 8080:9080 -t spring-boot-docker/spring-boot-docker --name spring-boot-docker-image
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.4)
2021-06-10 10:10:57.298 INFO 1 --- [ main] c.t.basic.tech.info.echo.EcoApplication : Starting EcoApplication v0.0.1-SNAPSHOT using Java 1.8.0_212 on a64d41b12767 with PID 1 (/spring-boot-docker-app.jar started by root in /)
2021-06-10 10:10:57.316 INFO 1 --- [ main] c.t.basic.tech.info.echo.EcoApplication : No active profile set, falling back to default profiles: default
2021-06-10 10:11:00.400 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 9080 (http)
2021-06-10 10:11:00.447 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-06-10 10:11:00.449 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.44]
2021-06-10 10:11:00.602 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-06-10 10:11:00.603 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3035 ms
2021-06-10 10:11:01.903 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2021-06-10 10:11:02.868 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9080 (http) with context path ''
2021-06-10 10:11:02.897 INFO 1 --- [ main] c.t.basic.tech.info.echo.EcoApplication : Started EcoApplication in 6.475 seconds (JVM running for 7.413)
Note: The option -p 8080:9080 says that expose port 8080 for internal port 9080.
Application running into docker can be accessed outside container.
We can list out all docker containers by docker ps command in the terminal and we can use the command docker stop <CONTAINER ID> for stopping the specific container
C:\Users\spring-boot-docker>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a64d41b12767 spring-boot-docker/spring-boot-docker "sh -c 'java $JAVA_O…" 17 minutes ago Up 17 minutes 0.0.0.0:8080->9080/tcp, :::8080->9080/tcp suspicious_banzai
C:\Users\spring-boot-docker>docker stop a64d41b12767
a64d41b12767
C:\Users\spring-boot-docker>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
C:\Users\spring-boot-docker>
Happy Learning 🙂