This extends Kubernetes (i.e. Minikube) – deploy a node js service.
Docker containers & Kubernetes for deploying Spring Boot microservices. As mentioned earlier in Kubernetes, Docker & Microservices interview Questions & Answers.
Docker gives you application isolation, and solves the dependency hell issues. For example, if you have two microservices servers, and both of which use Spring-boot. But, each of them uses a slightly different version of flask and other dependencies. Running these API servers under different containers provides an easy way to avoid the “dependency hell” issue.
Get the Spring-boot app going first
Step 1: Go to https://start.spring.io/ to create a skeleton spring-boot application. Click on “generate” to download the “minikube-springboot.zip” file.
Step 2: Unzip “minikube-springboot” inside the “projects folder” and open this folder with your IDE of your choice. I am opening the with “Visual Studio Code” IDE.
Step 3: Create “HelloController.java” inside the package “com.myapp.minikubespringboot.controller;” under “src/main/java”. “controller” is a new folder.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.myapp.minikubespringboot.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @RequestMapping("/hello") public String hello(){ return "Hello from Spring boot on Minikube"; } } |
Step 4: The “pom.xml” looks like
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?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 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.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.myapp</groupId> <artifactId>minikube-springboot</artifactId> <version>0.0.1-SNAPSHOT</version> <name>minikube-springboot</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</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> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> |
Step 5: Open a terminal windo and run:
|
1 2 |
~/projects/minikube-springboot]$ mvn clean package |
This builds the jar file “minikube-springboot-0.0.1-SNAPSHOT.jar” in the “target” folder. Lets’s run the app.
|
1 2 |
~/projects/minikube-springboot]$ java -jar target/minikube-springboot-0.0.1-SNAPSHOT.jar |
Step 6: Open a browser and execute: “http://localhost:8080/hello”
Which outputs:
“Hello from Spring boot on Minikube”.
Dockerfile
Step 7: Create the “Dockerfile” in the base directory.
|
1 2 3 4 5 6 7 8 |
FROM openjdk:8-jdk-alpine VOLUME /tmp ARG DEPENDENCY=target/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.myapp.minikubespringboot.MinikubeSpringbootApplication"] |
Step 8: The pom.xml file needs to be updated as shown below with additional plugins.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
<?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 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.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.myapp</groupId> <artifactId>minikube-springboot</artifactId> <version>0.0.1-SNAPSHOT</version> <name>minikube-springboot</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <dockerfile-maven-version>1.4.3</dockerfile-maven-version> <docker.image.prefix>springio</docker.image.prefix> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</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> </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.9</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> |
Step 9: Run the “./mvnw” command to build the image.
|
1 2 |
~/projects/minikube-springboot]$ ./mvnw install dockerfile:build |
Now check the image that was built from the “Dockerfile”
|
1 2 3 4 5 |
~/projects/minikube-springboot]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE springio/minikube-springboot latest a034dc38dac9 3 minutes ago 123MB openjdk 8-jdk-alpine a3562aa0b991 4 months ago 105MB |
If you have a repository access you can configure it in your pom.xml and push the artefacts using
|
1 2 |
~/projects/minikube-springboot]$ ./mvnw dockerfile:push |
Step 10: Run the image on the container.
|
1 2 |
~/projects/minikube-springboot]$ docker run -p 8080:8080 -t springio/minikube-springboot |
The application is running inside the Docker container. You can open a browser now and type the URL “http://localhost:8080/hello“.
Step 10: Stop the container.
|
1 2 |
~/projects/minikube-springboot]$ docker ps |
to get the running container id and then stop the container as shown
|
1 2 |
~/projects/minikube-springboot]$ docker stop 7fea98789e00 |
Kubernetes – minikube
Step 11: Start the minikube
|
1 |
$ minikube --vm-driver=hyperkit start |
Step 12: Run the following command to make minikube use local docker registry. Otherwise, minikue will seek image from other public Docker registry.
|
1 |
$ eval $(minikube docker-env) |
Step 13: Check if the cluster is up.
|
1 2 3 4 5 6 |
$ kubectl cluster-info Kubernetes master is running at https://192.168.64.8:8443 KubeDNS is running at https://192.168.64.8:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. |
The –image-pull-policy Never means Minikube doesn’t try to pull the image from a registry, but takes it from the local Docker host instead.
|
1 2 |
$ kubectl run my-springboot-on-k8s --image=springio/minikube-springboot:latest --port=8080 --image-pull-policy Never |
Step 14: Get the deployments
|
1 2 3 4 |
$ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE my-springboot-on-k8s 1/1 1 1 7s |
You can also view it via “$ minikube dashboard”
Step 15: Expose the deployment
|
1 2 |
$ kubectl expose deployment my-springboot-on-k8s --type=NodePort |
View the services:
|
1 2 3 4 5 6 |
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40h minikube-node-server-replicaset-service NodePort 10.107.110.228 <none> 9090:30036/TCP 16h my-springboot-on-k8s NodePort 10.104.150.82 <none> 8080:31873/TCP 32s |
Run the services:
|
1 2 |
$ minikube service my-springboot-on-k8s --url |
Which outputs: http://192.168.64.8:31873
You can run “http://192.168.64.8:31873/hello” on a browser.
Delete the service & deployment
|
1 2 |
$ kubectl delete svc my-springboot-on-k8s |
|
1 2 |
$ kubectl delete deployment my-springboot-on-k8s |
|
1 2 3 |
$ minikube stop $ minikube delete |


