Deploying a Spring Boot App with Docker in a Kubernetes Cluster

Deploying a Spring Boot App with Docker in a Kubernetes Cluster 

This article was originally written by “Kemane Donfack” on the blog: https://blog.numericaideas.com/deploying-springboot-app-with-docker-and-kubernetes

Introduction

In the modern application ecosystem, it is becoming increasingly common to use technologies like Docker and Kubernetes to deploy applications in an efficient and scalable manner. By using Docker to containerize applications and Kubernetes to orchestrate them, developers can easily manage and deploy applications at scale.

The following lines will clearly differentiate between containerized and orchestration terms in a beginner-friendly way along with a practical sample using Java programming language.

DockerImage

Moving to the following sections, we assume that you have Java (OpenJDK 11), Docker, and Kubernetes properly installed on your computer.

The YouTube Channels in both English (En) and French (Fr) are now accessible, feel free to subscribe by clicking here.

Docker

Docker is an open-source tool for containerizing applications, it encapsulates an application with all the dependencies needed for it to run. Docker containers are lightweight and easy to move around, allowing applications to be deployed quickly and efficiently on any system that supports Docker.

The advantage of containerizing applications is that it allows applications to be separated from operating systems. Applications can be deployed on different operating systems without having to worry about configuration differences. It also makes it easier to scale and manage applications because containers can be moved easily between servers.

To containerize an application with Docker, you must first create a file called Dockerfile that describes the steps needed to create a container. This file describes the commands to install the dependencies, configure the application and start the main process.

Once the Dockerfile is created, you can build the container image using the docker build command, which uses the instructions in the Dockerfile to create an image that can be used to start a container.

Kubernetes

Kubernetes aka k8s is an open-source container orchestration tool, it allows you to manage containers’ clusters using concepts such as pods, replicasets, and deployments. Pods are groups of containers that work together to run an application, while Replicasets ensure that the number of running pods matches the number specified in the configuration, in the other hand Deployments manage application updates by defining scaling and rollback policies. Kubernetes also provides high availability, load balancing, and monitoring capabilities.

Kubernetes has several advantages for managing application containers, including:

  • Scalability: makes it easier to scale applications by increasing or decreasing the number of running pods in regard to the application’s usage, also refers to as horizontal scaling.
  • High availability: automatically manage the distribution of containers across different nodes to ensure application availability.
  • Flexibility: supports many types of containers, including Docker, and can be used on different platforms, including public and private clouds.
  • Automation: automates many container management tasks, such as scaling, upgrading, and deployment.
  • Integration: facilitates the integration of different services and tools, such as monitoring systems, storage systems, and so on.
  • Update: when updates are available, it’s easy to apply them using Kubernetes, without interrupting the services.

Deploying with Docker and Kubernetes

Application Preparation

To deploy an application with Docker, you must first create a configuration file called Dockerfile which describes the steps needed to build the application’s image.

Building the Image

Next, the Dockerfile is used to build the image of the application using the docker build command. This image is then stored in a Docker image registry like the famous Docker Hub.

Deploying the Image

Then, to deploy the application in a Kubernetes cluster, you need to create a configuration file called deployment.yaml which describes the deployment parameters such as the number of replicas (instances of the application), required resources, … etc.

Running the Application

Finally, with the configuration file in place, Kubernetes has everything to deploy the application in the cluster(s) using the command kubectl create -f deployment.yaml. It takes care of creating the necessary containers, placing them on the appropriate nodes, and managing them as needed (restarting, scaling, .. etc).

Demo: Spring Boot Application Deployment in a Kubernetes Cluster

In this demo, we will deploy a Spring Boot application using Docker and Kubernetes with MySQL as the database management system. A Dockerfile is created to build the image of the application and then used to deploy the application on a Kubernetes cluster.

Clone the Github Repository

Let’s start by cloning the project from the github repository:

git clone https://github.com/numerica-ideas/community

Then, go to the directory that contains the project:

cd community/kubernetes/springboot-docker-kubernetes-setup

Project Compilation

To compile the project, let’s run the following command if you are on a Unix based operating system:

./mvnw clean install -DskipTests

The following works for Windows instead:

mvnw.cmd clean install -DskipTests

After that, you will get the following files and directories as illustrated in the screenshot:
SpringBootBuild

Presentation of the Dockerfile

The Dockerfile is used to create a Docker image of our application. Actually, it contains instructions to:

  • Set the Java version to use (OpenJDK 11).
  • Specify the folder in which the executable Jar file should be found at.
  • Rename the jar file to app.jar.
  • Expose the port 8020 defined in the applications.properties file that Spring-Boot embedded Tomcat server will use to run the App.
  • Provide the entry point (command to run the App), it’s equivalent to java -jar /app.jar.
FROM openjdk:11
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
EXPOSE 8020
ENTRYPOINT ["java", "-jar", "/app.jar"]

It’s important to note that the Dockerfile must be placed at the root of our project for the commands to work properly.

Creating the Docker Image

As said previously, creating a Docker image for the App is done via the docker build command by specifying the path of the Dockerfile, it reads the instructions in the Dockerfile and creates the corresponding image useful to deploy our application.

In the future instructions, lugar2020 is my Docker Hub ID so replace it with yours after creating your account.

Start the Docker process, then run this command which specifies the image tag (-t: username/app_name) and the Dockerfile path (dot: current directory):

docker build -t lugar2020/crud-spring-boot .

DockerImage

Uploading the Image to the Docker Hub

Once we have created our application image, we can upload it to the Docker Hub using the docker push command. This will allow us to easily upload the image to a Kubernetes cluster for deployment purposes.

First, sign in to your Docker Hub account:

docker login

DockerLogin

Check the Docker image existence with the command:

docker images

DockerImages

Push the application image to your Docker Hub repository:

docker push lugar2020/crud-spring-boot

DockerPush

Deploying the Application

To deploy in a Kubernetes cluster, we need two manifest files for both Spring-Boot and for Mysql, these files are respectively of Service and Deployment kinds.

The deployment manifest file defines a deployment on Kubernetes. It allows you to deploy and manage one or more replicas (instances) of your App in the cluster. The file describes the features (pod, replicas) that your App needs to run and to be accessible by users.

A Kubernetes service manifest file is used to describe a Kubernetes service which exposes the App to external users by using a standard port and IP address and mapping those requests to Kubernetes pods running the applications. It defines how services should work and which pods they should connect to.

Together, the service file and the deployment file define the behavior of the Kubernetes App and how it will be managed.

In our case, the deployment app-deploy.yml file will allow to deploy our Spring-Boot App (we will use the image previously pushed on the docker hub) in the cluster and the mysql-deploy.yml file will do the same for MySQL (an existing image will be used for MySQL: mysql:5.7). The mysql-service.yml file makes our database accessible inside the cluster, the app-service.yml allow our Spring-Boot App to be accessible for users outside the cluster.

The app-deploy.yml file looks like the following:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deploy
  labels:
   app: backend-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend-app
  template:
    metadata:
      labels:
        app: backend-app
    spec:
      containers:
      - name: backend-container
        image: lugar2020/crud-spring-boot
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8020
        env:
        - name: DB_HOST
          value: mysqldb
        - name: DB_NAME
          value: crud-db
        - name: DB_USERNAME
          value: root
        - name: DB_PASSWORD
          value: Password123

While its associated service file nammed app-service.yml, is as below:

apiVersion: v1
kind: Service
metadata:
  name: springboot-backend
  labels:
    name: backend-service
spec:
  type: NodePort
  ports:
    - port: 8020
      targetPort: 8020
      nodePort: 30006
  selector:
    app: backend-app

The property spec:selector in the service file identifies which pods (deployments units) will be included in the service. For this case, it means the deployments that has the label app: backend-app defined in the app-deploy.yml file.

The same goes by for MySQL configurations, you’ll find all these files in the kubernetes folder in the repository.

In case you are using Docker Desktop, you have to enable Kubernetes from its settings:

EnableKubernetes

To deploy the App, a script has been created which you can run from within the root folder, it applies all the Kubernetes deployment/service manifests:

./deploy.sh

Once deployed, feel free to run the following command to display all Kubernetes resources (pods, services, etc …):

kubectl get all

KubernetesResources

Finally, we can open the App once exposed outside the cluster with the script ./expose.sh which uses the port forwarding method to serve it on localhost using the port 4646.

ClusterExposedOnLocalhost

Environment Variables

Environment Variables are parameters that can be set and used to configure applications and services. In our case we have defined some in the application.properties file and we assigned values to these variables at deployment time to the App from the app-deploy.yml file in the containers.env key pairs.

The application.properties file is as follow:

spring.datasource.url=jdbc:mysql://${DB_HOST}/${DB_NAME}?serverTimezone=UTC
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

For a production grade application, the way to provide these variables could differ but the general idea remains passing them to the App.

The complete source code of the project is available on GitHub.

———————

We have just started our journey to build a network of professionals to grow even more our free knowledge-sharing community that’ll give you a chance to learn interesting things about topics like cloud computing, software development, and software architectures while keeping the door open to more opportunities.

Does this speak to you? If YES, feel free to Join our Discord Server to stay in touch with the community and be part of independently organized events.

———————

Conclusion

To summarize, Docker and Kubernetes are incredibly powerful and flexible tools for deploying containerized applications in clusters. Using these two tools together makes it possible to deploy applications efficiently, reliably, and in a productive manner by taking advantage of Docker’s isolation and Kubernetes’ clusters management. Having a good understanding of both in terms of features/concepts is a must to put them in a perfect symbiose.

Thanks for reading this article, recommend and share if you enjoyed it. Follow us on Facebook, Twitter, and LinkedIn for more content.

Leave a Reply

Your email address will not be published. Required fields are marked *

Press ESC to close