In this tutorial I’ll explain how you can implement a continuous Spring Boot deployment in Kubernetes. A small code change will trigger a new Docker image build and an instant deploy of a new pod in your cluster.

This tutorial is executed on macOs.

Jib is an open-source, fast and simple Java container image builder from Google that handles all the steps of packaging your application into a container image. It does not require you to write a Dockerfile.

We will use the jib-maven-plugin to create a Docker image for our application.

Next we will setup a local minikube cluster and create a Kubernetes deployment. Skaffold will help use to make this deployment continuous.

First install minikube, kubectl and Skaffold and start your minikube cluster:

$ brew cask install minikube

$ minikube start

$ brew install skaffold

$ brew install kubernetes-cli

Check the IP of your minikube instance and verify if you can visit the minikube dashboard:

$ minikube ip

192.168.99.101 # most of the time it's 192.168.99.100

$ minikube dashboard

Now create your Spring Boot project. You can use this example project to get started. Open the project in your favorite IDE and just try to build it:

$ mvn clean install

Go the pom.xml and verify the configuration of the jib-maven-plugin .

We will use registry.hub.docker.com/openjdk:8-jdk-alpine as base image.

Access the terminal of your IDE and execute the following command to point remote Docker daemon of minikube:

$ eval $(minikube docker-env)

We will use the minikube daemon so we can just build our Docker image and minikube can access it without the need to push the image, or pull the image from a Docker Registry.

Build the Docker image using the jib plugin:

$ mvn compile jib:dockerBuild

This Docker image is accessible on our minikube node because we use the remote daemon. We will create a deployment on minikube by using the kubernetes/deployment.yml

apiVersion: apps/v1

kind: Deployment

metadata:

name: spring-deployment

spec:

replicas: 1

selector:

matchLabels:

app: spring-boot-jib

template:

metadata:

labels:

app: spring-boot-jib

spec:

containers:

- name: spring-boot-jib-pod

image: lvthillo/my-app

imagePullPolicy: IfNotPresent

ports:

- name: http

containerPort: 8080

---

apiVersion: v1

kind: Service

metadata:

name: spring-boot-jib-service

spec:

type: NodePort

ports:

- protocol: TCP

port: 8080

nodePort: 32321

selector:

app: spring-boot-jib

This template will deploy a pod from our lvthillo/my-app image and port 8080 of the pod will be exposed. The template will also create a service of type NodePort which will map port 8080 to NodePort 32321.

$ kubectl create -f kubernetes/deployment.yml

deployment.apps/spring-deployment created

service/spring-boot-jib-service created $ kubectl get pods

NAME READY STATUS RESTARTS AGE

spring-deployment679-rhmzn 1/1 Running 0 18s

Visit the application on your minikube ip and the port which we’ve defined as nodePort: 192.168.99.101:32321

We have deployed our Spring Boot application in minikube! We will use another great tool developed by Google to automate the deployment to minikube. The tool is called skaffold.

Write a skaffold.yml in the root of the project.

apiVersion: skaffold/v1beta4

kind: Config

# Enforce SKaffold to use Jib

build:

local:

push: false

# Generated artifact

artifacts:

- image: lvthillo/my-app

# Use jibMaven

jibMaven: {}

# Execute deployment.yml

deploy:

kubectl:

manifests:

- kubernetes/deployment.yml

Run Skaffold in development mode. This will build our image and deploy it to minikube for every change we make in our project.

$ skaffold dev --trigger notify

A small change will already be picked up and Skaffold will trigger automatically a new build of the Docker image:

A new pod is created:

And the change is deployed:

Conclusion

We used two very cool tools developed by Google which enables continuous deployment of our project to minikube. You can also use jib to automate the push of your image to a Docker Registry and even to enable an continuous deployment to a Kubernetes cluster hosted in the cloud.