Automated CI/CD Pipeline for Spring Boot Application

 

1.    Introduction

                              This project is a Continuous Integration/Continuous Deployed for a dummy spring boot application, the entire process is automated using triggers such as git commit, the pipeline is done using DevOps tools such as Git, Maven, JUNIT, GitHub Actions, Docker and Nagios. The aim is to automate stages of software development such as build, test, deploy and monitor using modern industry standard practices, minimizing manual intervention and enhancing reliability of the application development process. The implementation demonstrates how automation and containerization simplify software delivery and ensure application uptime through monitoring.



Objectives

Part 1: CI - Continuous Integration (GitHub Actions + Maven + JUnit)

  • Automate build and testing using GitHub Actions.
  • Integrate Maven for dependency management and packaging.
  • Ensure code quality using JUnit testing.
  • Achieve consistent and reproducible builds through automated workflows.


Part 2: CD - Continuous Deployment (Docker + Docker Hub + Self-Hosted Runner)

  • Containerize the Spring Boot application using Docker.
  • Automate image build and push process to Docker Hub.
  • Deploy the container on a self-hosted runner or virtual machine.
  • Verify application endpoints and ensure smooth deployment.

Part 3: Monitoring & Alerting (Nagios)

  • Implement Nagios for application and container monitoring.
  • Configure check_http plugin to track service uptime and response.
  • Set up service definitions and configurations for continuous health checks.
  • Demonstrate proactive alerting when the container is down.
  •  

2.    Name of the Containers Involved and Download Links

Container Name

Purpose / Description

Download or Base Image Link

Spring Boot Application Container (jlol123/cicd)

Custom container built for deploying the Spring Boot application. It runs the compiled JAR file (Private Repo) (springBootCicd.jar) on port 9091 and is hosted on Docker Hub for reuse and deployment.

jlol123/cicd | Docker Hub

Base Image – Eclipse Temurin (OpenJDK 21) (eclipse-temurin:21-jdk)

Provides the Java 21 runtime environment and libraries required to execute the Spring Boot application inside the container. This is the base image used in the Docker file.

https://hub.docker.com/_/eclipse-temurin

 


3.    Name of the other software involved along with the purpose

Software / Tool Name

Purpose / Role in Project

GitHub Actions

Used as a CI/CD automation platform to build, test, and deploy the Spring Boot application directly from the GitHub repository. Replaces Jenkins for workflow automation.

Maven

Build automation and dependency management tool. Compiles the Java code, packages it as a JAR, and manages external dependencies during the CI process.

Junit

Testing framework used to run unit tests automatically during the Maven build phase to ensure code reliability and correctness.

Docker

Used for containerization of the Spring Boot application, building images, and deploying containers efficiently. Also enables portability across environments.

Nagios

Monitoring tool used to continuously check the health and performance of the deployed Spring Boot container and raise alerts when downtime or issues occur.

Virtual Machine / Self-Hosted Runner

Acts as the server where GitHub Actions workflows execute. Hosts Docker and Nagios, allowing custom build and deployment processes.

Git & GitHub

Version control system and remote repository used for source code management and workflow automation triggers (push/pull requests).

 

4.    Architecture

Part

Objective

Key Tools / Software Used

Containers Involved

Part 1 – Continuous Integration (CI)

Automate the build and testing of the Spring Boot application whenever new code is pushed to GitHub.

GitHub Actions, Maven, JUnit, Git

No separate container (runs on self-hosted GitHub runner)

Part 2 – Continuous Deployment (CD)

Containerize the tested application and automatically deploy it on a self-hosted virtual machine.

Docker, DockerHub, GitHub Actions, Virtual Machine

jlol123/cicd (Spring Boot container)
Base: eclipse-temurin:21-jdk

Part 3 – Continuous Monitoring (CM)

Monitor application health, uptime, and performance using Nagios.

Nagios, check_http plugin

jasonrivers/nagios (Nagios monitoring container)

 

Architecture

      Fig 1: CICD Pipeline 


5.    Architecture Description


The overall architecture of the project integrates three major DevOps stages — Continuous Integration (CI), Continuous Deployment (CD), and Continuous Monitoring (CM) — to automate the entire software lifecycle. In the CI stage, GitHub Actions triggers automatically when code is pushed to the repository. It uses Maven to build the Spring Boot application and JUnit to perform automated testing. This ensures that only verified, error-free code proceeds to the next stage, resulting in a tested JAR artifact ready for deployment.


The CD stage utilizes Docker to containerize the tested application using the Eclipse Temurin (OpenJDK 21) base image. The image is tagged and pushed to DockerHub, then deployed automatically on a self-hosted runner (virtual machine) via GitHub Actions. Finally, the CM stage employs Nagios and its check_http plugin to continuously monitor the health and availability of the deployed container on port 9091. This architecture ensures an end-to-end automated workflow where software is built, tested, deployed, and monitored seamlessly with minimal human intervention — achieving high reliability, scalability, and operational efficiency.

 

Preface

 

GitHub Actions

GitHub Actions is a CI/CD platform that automates workflows directly within GitHub repositories. It lets developers build, test, and deploy code automatically based on events like pushes or pull requests. With customizable workflows and easy integration, it helps streamline software development and delivery.

Marketplace

Use Marketplace Actions GitHub Marketplace provides ready-made actions to automate tasks like testing, deployment, and setup. These reusable components simplify workflows and save time. Just reference them in your YAML file—no need to build from scratch. Explore more at github.com/marketplace/actions.

Application

A dummy Spring Boot application is used in this project with just one controller and 3 api endpoints, built with the Spring Boot framework, this app is just used for learning, testing, or demonstrating basic functionality. It's useful for testing deployments, monitoring setups, or integrating tools like Nagios, GitHub Actions, or Docker

NOTE : The CICD pipeline mentioned could be applied to any spring boot application, it is just that dummy application was used here to reduce development time.

package com.example.CICD.Controller;

 

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class MainController {

 

    @GetMapping("/")

    public String getHome() {

        return "Welcome to the Home Page of the Website";

    }

 

    @GetMapping("/add5/{id}")

    public String addFive(@PathVariable Integer id) {

        int b = id + 5;

        return Integer.toString(b);

    }

 

    @GetMapping("/add10/{id}")

    public String addTen(@PathVariable Integer id) {

        int b = id + 10;

        return Integer.toString(b);    }  }

6.    Part 1

 CI - Continuous Integration (GitHub Actions + Maven + JUnit)

  1. Automate build and testing using GitHub Actions.

GitHub Actions automates tasks like building, testing, and deploying code by running workflows defined in your repository. These workflows are triggered by events (e.g., push, pull request) and contain steps that run specific commands.

 

How to create GitHub Actions?

1. Go to Your Repository

Navigate to the GitHub repository where you want to add GitHub Actions.

Create a Workflow File

1.     Click on the Actions tab in your repo.

2.     Click "New workflow" or "Set up a workflow yourself".

3.     This creates a YAML file inside the .github/workflows/ directory. 3. Define Your Workflow

[The code to define our workflow is given below] define workflow inside the yaml file

4.     Commit and Push  git add .github/workflows/<your-workflow-name>.yml git commit -m "Add GitHub Actions workflow" git push origin main

A screenshot of a computer

AI-generated content may be incorrect. 

 

Runners are the servers that execute these workflow jobs.

      GitHub-hosted runners are managed by GitHub and ready to use.

 

      Self-hosted runners are set up by you for more control and customization. We would be using Self_hosted runners/servers

 

Why Self-hosted runners?

Self-hosted runners are used in GitHub Actions when you need:

      More control over the environment (custom tools, OS, dependencies).

      Faster builds by reusing cached files or avoiding queue times.

      Access to internal resources, like private servers or databases.

      Cost efficiency for large or frequent workflows, avoiding GitHub-hosted runner limits.

Configuring Self Hosted Runners

1.     Go to your repo on GitHub → SettingsActionsRunners.

2.     Click "Add Runner", choose your OS, and follow the instructions.

 

 

A screenshot of a computer

AI-generated content may be incorrect. 

3.     Download the runner package on your server/machine.

# Create a folder

$ mkdir actions-runner && cd actions-runner

# Download the latest runner package

$ curl -o actions-runner-linux-x64-2.325.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.325.0/actions-runner-linux-x642.325.0.tar.gz

# Optional: Validate the hash

$ echo "5020da7139d85c776059f351e0de8fdec753affc9c558e892472d43ebeb518f4  actionsrunner-linux-x64-2.325.0.tar.gz" | shasum -a 256 -c

# Extract the installer

$ tar xzf ./actions-runner-linux-x64-2.325.0.tar.gz

 

4. Extract the package and run the config script provided by GitHub

# Create the runner and start the configuration experience

$ ./config.sh --url https://github.com/Jivinlol/CICD --token

BOLGOS4WMS3UA7NEIN25XUTIMLM6I # Last step, run it!

$ ./run.sh

 

A screenshot of a computer

AI-generated content may be incorrect. 

 

A screenshot of a computer

AI-generated content may be incorrect. 

 

 

We should also define the workflow/cicd pipeline in github workflows directory Paste the following yaml file in directory under github actions

name: Java CI with Maven

on:   push:

    branches: [ "main" ]

  pull_request:

    branches: [ "main" ]

jobs:   build:

    runs-on: cicd

    steps:

-  uses: actions/checkout@v4     - name: Set up JDK 21

      uses: actions/setup-java@v4

      with:

        java-version: '21'

        distribution: 'temurin'

        cache: maven                                     

-  name: Build with Maven

      run: mvn -B package --file pom.xml     - name: Build and push docker image        uses: mr-smithers-excellent/docker-build-push@v6

      with:

        image: jlol123/cicd

        tags: latest

        registry: docker.io

        username: ${{ secrets.DOCKER_USERNAME }}

        password: ${{ secrets.DOCKER_PASSWORD }}

  docker_contianer:         needs: build

        runs-on: cicd

        steps:

-  name: Login to Docker Hub

             uses: docker/login-action@v3

             with:

              username: ${{ secrets.DOCKER_USERNAME }}

              password: ${{ secrets.DOCKER_PASSWORD }}            - name: Pull image from docker

             run:  docker pull jlol123/cicd:latest            - name: Run docker container

             run: docker run -d -p 9091:9091 jlol123/cicd:latest

-  name: Sleep for 5 Minutes

             run: sleep 32

 

  1. Integrate Maven for dependency management and packaging.

With github actions:

The following code inside the main yaml file is responsible for maven to build and package our java file 

Code:   build:

    runs-on: cicd

    steps:

    - uses: actions/checkout@v4     - name: Set up JDK 21

      uses: actions/setup-java@v4

      with:

        java-version: '21'

        distribution: 'temurin'

        cache: maven                       - name: Build with Maven

      run: mvn -B package --file pom.xml

runs-on: cicd

       This specifies the runner where the job should run.

 

       cicd is a label for a self-hosted runner, meaning the job will execute on a machine you or your team have set up and registered with GitHub.

 

 

Steps Breakdown

1. Checkout the Code

- uses: actions/checkout@v4

       This step checks out the repository code onto the runner.

       It allows the runner to access your project files so it can build and test them.

 

2. Set Up JDK 21

- name: Set up JDK 21   uses: actions/setup-java@v4   with:

    java-version: '21'     distribution: 'temurin'

    cache: maven

       This uses the setup-java action to install Java Development Kit (JDK) 21 from the

Temurin distribution.

       cache: maven enables caching of Maven dependencies to speed up future builds by avoiding re-downloading libraries.

3. Build with Maven

- name: Build with Maven   run: mvn -B package --file pom.xml

       This step runs Maven in batch mode (-B) to create a build artifact.

 

       It uses the pom.xml file in the root directory to resolve dependencies, compile the code, and package it (typically into a .jar or .war file).

 

In conclusion, this job checks out your Java project's code, sets up Java 21 with dependency caching, and builds the project using Maven—automating the core CI step in your workflow.

A screenshot of a computer

AI-generated content may be incorrect. 

 

 

 

 

As shown in the output screen the file is being built and stored at

/home/jks/actions-runner/_work/CICD/CICD/target as a jar file

 

 

 

  1. JUnit testing for application logic and error mitigation..

 

The same code above is also responsible for junit testing of unit test cases provided in test directory, while the YAML snippet you shared doesn’t explicitly mention JUnit testing, Maven’s default package phase includes running tests— this means JUnit tests (if present) will automatically execute as part of the build. 

When you run:

                          mvn -B package --file pom.xml

Maven follows the standard build lifecycle, which includes phases like compile, test, package, etc.

 

The junit test code given in repo and output are pasted below

 

Code:

 

package com.example.CICD.Controller;

import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(MainController.class) public class MainControllerTest {

    @Autowired     private MockMvc mockMvc;

    @Test     public void testHome() throws Exception{         mockMvc.perform(get("/"))

                .andExpect(status().isOk())

                .andExpect(content().string("Welcome to the Home Page of the Website"));

    }

}

Output:

A screenshot of a computer program

AI-generated content may be incorrect. 

A computer screen with white text

AI-generated content may be incorrect. 

A screenshot of a computer program

AI-generated content may be incorrect. 

A screenshot of a computer

AI-generated content may be incorrect.

7.    Part 2

Continuous Deployment (Docker + DockerHub + Self-Hosted Runner)

4.     Containerize the Spring Boot application using Docker.
DockerFile Code

FROM eclipse-temurin:21-jdk

# Copy the JAR file (built via Maven)

EXPOSE 9091

ADD target/springBootCicd.jar springBootCicd.jar

# Run the application

ENTRYPOINT ["java", "-jar", "/springBootCicd.jar"]
Step-by-Step Explanation

 

To containerize the Spring Boot application, we begin by creating a Dockerfile that defines how the application will be built and run inside a container.

1.       Base Image:
The first line,

FROM eclipse-temurin:21-jdk

specifies the base image. Here, we use the official Eclipse Temurin JDK 21 image, which provides a lightweight and reliable Java runtime environment needed to execute Spring Boot applications.

2.       Expose Application Port:

EXPOSE 9091

This line informs Docker that the application inside the container will listen on port 9091. While this doesn’t actually publish the port by itself, it serves as documentation and allows tools like Docker Compose or Kubernetes to map it correctly.

3.       Add Application JAR:

ADD target/springBootCicd.jar springBootCicd.jar

Here, we copy the built JAR file (created using Maven or Gradle) from the local target/ directory into the container’s root directory. The JAR file contains the compiled Spring Boot application and all its dependencies.

4.       Run the Application:

ENTRYPOINT ["java", "-jar", "/springBootCicd.jar"]

This line defines the command that will run when the container starts. It launches the Spring Boot application by executing the JAR file using the Java runtime.

 

5.Automate image build and push process to DockerHub.
Docker Build and Push:

The following code inside the main yaml file is responsible for our application to be containerized using docker and push that image of the container which is built to docker hub we will later use that image to deploy our application 

 

Code:

-      name: Build and push docker image        uses: mr-smithers-excellent/docker-build-push@v6

      with:

        image: jlol123/cicd         tags: latest         registry: docker.io

        username: ${{ secrets.DOCKER_USERNAME }}         password: ${{ secrets.DOCKER_PASSWORD }}

 

Step Name:

-      name: Build and push docker image

       This labels the step, making it clear in the workflow logs that the job is building and pushing a Docker image.

Action Used:

uses: mr-smithers-excellent/docker-build-push@v6

       This uses a popular, community-maintained GitHub Action designed to simplify building and pushing Docker images.

 

       The @v6 specifies the version of this action.

 

 

      With:                       these are all parameters provided for the action to work properly         image: jlol123/cicd         tags: latest         registry: docker.io

        username: ${{ secrets.DOCKER_USERNAME }}         password: ${{ secrets.DOCKER_PASSWORD }}

What Happens in This Step:

1.     The action builds a Docker image from the repository’s Dockerfile (assumed to be in the root or default location).

 

2.     The image is tagged as jlol123/cicd:latest.

 

3.     The action logs in to Docker Hub using the provided secrets.

 

4.     The built image is pushed to the Docker Hub repository under the jlol123 namespace.

 

5.     After this step completes, the image is available on Docker Hub for deployment or sharing.

 

A screenshot of a computer

AI-generated content may be incorrect. 

 

The image has been built and pushed to our docker hub repository 

 

With these steps our first job gets over and post job clean up is invoked to clean up resources after a workflow job finishes. This includes stopping services, deleting temporary files, or releasing any system resources used during the job.

A screenshot of a computer

AI-generated content may be incorrect. 

A screenshot of a computer

AI-generated content may be incorrect. 

 

Job run in parallel generally in job runners but our second job was configured to wait for the first build job to finish otherwise we could not deploy our application.



6.Deploy the container on a self-hosted runner or virtual machine.

Pull Docker Image:

 This comes as second job after the build job and it generally runs in parallel but we are forcing it to run sequentially , the following code in yaml file is responsible for pulling  the docker image

 

  docker_contianer:         needs: build         runs-on: cicd         steps:

-      name: Login to Docker Hub              uses: docker/login-action@v3

             with:

              username: ${{ secrets.DOCKER_USERNAME }}               password: ${{ secrets.DOCKER_PASSWORD }}

-      name: Pull image from docker              run:  docker pull jlol123/cicd:latest

 

Job Dependency needs: build

       This makes the docker_container job depend on the successful completion of the build job.

       It ensures that the Docker image is built and pushed before trying to pull it.

 

Runner Specification runs-on: cicd

       Same as before runs it on a self hosted docker runner  name cicd

Step 1: Login to Docker Hub

 name: Login to Docker Hub   uses: docker/login-action@v3

  with:

    username: ${{ secrets.DOCKER_USERNAME }}     password: ${{ secrets.DOCKER_PASSWORD }}

       Uses the official docker/login-action to authenticate with Docker Hub.

       This login is required before pulling a private image

Step 2: Pull Docker Image

-  name: Pull image from docker   run: docker pull jlol123/cicd:latest

       This step pulls the Docker image jlol123/cicd:latest from Docker Hub to the runner.

       It ensures the image built in the previous build job is now available locally on the runner for use (e.g., to run or deploy a container).

Output:

A black screen with white text

AI-generated content may be incorrect. 

 





 



A screenshot of a computer

AI-generated content may be incorrect. 

6. Deploy Docker Container:

                              We deploy the docker container in our own virtual box which is installed in our machine, we could also use kubernetes, aws ec2 instance to deploy these images but aws ec2 is paid tool and kubernetes is useful when there are multiple deployments needed to be made, Since this is an learning project the image and pulled and the container is deployed in the same machine, this would also make monitoring easier in the upcoming stages.

            The following code is responsible for running the docker container 

-  name: Run docker container

             run: docker run -d -p 9091:9091 jlol123/cicd:latest

       docker run: Starts a new container from the jlol123/cicd:latest image.

       -d: Runs the container in detached mode, meaning it runs in the background.

       -p 9091:9091: Maps port 9091 on the host (self-hosted runner) to port 9091 inside the container.This allows services inside the container (like a Spring Boot app) to be accessed from outside using port 9091.

 

          - name: Sleep for 5 Minutes              run: sleep 320 

    We add sleep for 5 minutes to test application manually using browser and check the api endpoints 

 

Output:


 

 

 

 

A computer screen with white text

AI-generated content may be incorrect. 

                

Output:

When we manually go and check the api endpoints



 



 

This completes our pipeline now we will need to monitor our application

 

8.    Part 3

Monitoring & Alerting (Nagios)

1 .Nagios Check_http


Nagios is an open-source tool for monitoring servers, applications, and network services. It alerts you when issues arise and confirms when they're resolved, helping ensure system uptime and reliability. It is suitable for our app since it can monitor it frequently and provide alerts 

 

 

 

Check_http

The check_http plugin monitors web servers by sending HTTP requests and checking response status and time. It alerts if the server is down or slow, ensuring web services stay available and responsive. 

We use the check_http plugin to monitor our website using nagios

 

Check_http plugin may not be there with default nagios core hence we install it with the following command

 

To install

$ sudo apt install nagios-plugins

 

To Check and verify installation 

$ /usr/lib/nagios/plugins/check_http --help

A computer screen with white text

AI-generated content may be incorrect. 

 

Once verified we use the command 

 

To monitor

$ /usr/lib/nagios/plugins/check_http -H localhost -p 9091 -u /-w 2 -c 5

 

Description:

This command uses the Nagios check_http plugin to monitor a web service on localhost at port 9091. It sends a request to the root path / and checks the response time. If the service takes longer than 2 seconds, a warning is triggered; over 5 seconds results in a critical alert. It ensures the service is up and performing within acceptable limits. This is useful for monitoring internal APIs or web apps.

 

Output:

 

When website is UP and RUNNING

 

When website is not Running



2. Nagios Service configuration

We define our own Nagios Service and Configure it to monitor the health and performance of our Spring Boot application running on port 9091 on the localhost.

Defining it as a service allows Nagios to regularly monitor the application, track its status over time, and trigger alerts automatically, unlike a one-time command which only provides a snapshot.

 

 

We create a cicd.cfg file which will be the service configuration file

On the path

 File  -   /usr/local/nagios/etc/objects

This is local to our machine it can differ based on the nagios installation 

 

 

Paste the code define host {   use             linux-server   host_name       spring-app   address         127.0.0.1

}

 

define service {   use                 generic-service   host_name           spring-app   service_description Spring App Health Check   check_command       check_http!-p 9091 -u /   normal_check_interval 5

  retry_check_interval 1

}

A screenshot of a computer

AI-generated content may be incorrect. 

For every five minutes it runs the http_check command and monitors our website

 

 

We now let nagios know we created a service configuration file 

To do that we will have to define it as a configuration file inside Nagios Configuration

 

 

 

Nagios Configuration 

The nagios.cfg file is the main configuration file for the Nagios Core monitoring system. It controls the overall behavior of Nagios and tells it where to find other important configuration files.

Key roles of nagios.cfg:

       Specifies paths to object definitions (hosts, services, contacts, etc.)

 

       Defines log file locations

 

       Controls scheduling and notification behavior

 

       Enables or disables features (like event handlers, flap detection, etc.)

 

The configuration file could be found at path

$ nano /usr/local/nagios/etc/nagios.cfg 

And add cfg_file=/usr/local/nagios/etc/objects/cicd.cfg

A screenshot of a computer

AI-generated content may be incorrect. 

 

Save the file 

Use command 

$ sudo /usr/local/nagios/bin/nagios -vv /usr/local/nagios/etc/nagios.cfg To check if nagios is working properly 

 

A screenshot of a computer program

AI-generated content may be incorrect. 

And restart nagios for changes to take place use cmd

$ sudo systemctl restart nagios 

 

 

 

Once restarted all configurations would have taken place in nagios to monitor our docker container which runs our spring boot application

 

3. Monitor Docker Container

Before starting our ci/cd pipeline and running our docker container

A screenshot of a computer

AI-generated content may be incorrect. 

 

Our nagios tries to hit our localhost:9091 api but the api isnt running hence it fails and gives us a critical warning to our website 

 

Once we start our application

 

 

We can see our spring app running and its status as UP we can also monitor  Other information by going into the spring-app details

 

 

Once we manually shut down our docker container we can see it goes to critical again we can configure the service to also send us alert message that our application is down on our future configurations.Since this is a simple spring boot application it wasn't required.

A computer screen with white text

AI-generated content may be incorrect. 

 

A screenshot of a computer

AI-generated content may be incorrect. 

A screenshot of a computer

AI-generated content may be incorrect. 

 

 

Our application is now has an automated build,test and deployed as well as monitoring to give alerts whether it is in good or critical condition

 

9.    What modification is done in the containers after downloading

Summary

      After pulling the base image (eclipse-temurin:21-jdk) we created a custom image by adding the compiled JAR, exposing the application port, setting the startup command, and then pushed the image to DockerHub. At runtime we configured port mapping, environment variables, restart policy, and volumes; finally Nagios was configured to monitor the running container.

 

    Build-time modifications

       

 

1.Choose base image
Dockerfile: FROM eclipse-temurin:21-jdk
→ The Java 21 runtime image is downloaded (automatically during build).

2. Add the application artifact into the image
Dockerfile: ADD target/springBootCicd.jar springBootCicd.jar
→ Copies the built JAR into the image.

3. Expose the application port
Dockerfile: EXPOSE 9091
→ Declares the application’s listening port inside the container.

4. Set the container startup command (entrypoint)
Dockerfile: ENTRYPOINT ["java", "-jar", "/springBootCicd.jar"]
→ Defines how the container starts the Spring Boot application.

5. Build the image (local or CI)

mvn -B package --file pom.xml

docker build -t jlol123/cicd:latest

→ Result: image jlol123/cicd:latest containing the app.

6. Push the image to DockerHub (CI or local)

docker login

docker push jlol123/cicd:latest

→ Image available remotely for deployment.

C. Runtime modifications (how the container instance is configured when started)

  1. Run the container and map the port
  2. docker run -d --name spring-app -p 9091:9091 jlol123/cicd:latest

→ Maps host port 9091 to container port 9091 so the app is reachable.

 

10.Github link

Jivinlol/CICD: cicd pipeline for devops

 

11.Outcomes of your DA

1.       Successful Implementation of an Automated CI/CD Pipeline:
A fully automated Continuous Integration and Continuous Deployment (CI/CD) pipeline was designed and implemented using GitHub Actions, ensuring that every code commit triggers automated build, test, and deployment processes. This greatly enhances development efficiency and consistency across environments.

2.       Seamless Continuous Integration with Maven and JUnit:
The integration of Maven for build automation and JUnit for testing ensured reliable, repeatable, and verified builds. This allowed early detection of code defects and maintained the overall quality of the software through automated validation.

3.       Containerization and Portability through Docker:
The project successfully containerized the Spring Boot application using Docker, resulting in a lightweight, portable, and consistent runtime environment. The generated Docker image (jlol123/cicd) was pushed to DockerHub, enabling version control, rapid deployment, and platform independence. This step significantly improved deployment speed and environment reproducibility.

4.       Automated Deployment on a Self-Hosted Runner:
Using a self-hosted GitHub Actions runner, the containerized application was automatically deployed to a virtual machine. This simulates real-world enterprise-grade DevOps environments where applications are continuously deployed to production or staging servers.

5.       Continuous Monitoring and Alerting via Nagios:
The integration of Nagios provided real-time monitoring and alert mechanisms for the deployed container. The check_http plugin continuously verified service availability on port 9091, ensuring proactive issue detection and application uptime tracking.

6.       Operational Efficiency and Reliability:
The pipeline minimized manual intervention, reduced deployment errors, and accelerated release cycles. Automated workflows improved system reliability, while containerization and monitoring ensured stability across multiple environments.

7.       Comprehensive DevOps Lifecycle Demonstration:
The project demonstrated an end-to-end DevOps lifecycle — covering source control, build automation, testing, containerization, deployment, and monitoring — providing hands-on experience with industry-relevant tools such as GitHub Actions, Maven, JUnit, Docker, and Nagios.

12. Conclusion

This project successfully implemented a complete DevOps CI/CD pipeline integrating Continuous Integration, Deployment, and Monitoring using open-source tools. Through GitHub Actions, Maven, and JUnit, the build and testing processes were automated, ensuring code reliability and consistency.

The application was containerized with Docker, enabling platform independence, scalability, and faster deployments, while Nagios monitoring provided continuous performance tracking and proactive alerts. Overall, the project demonstrates how automation and containerization enhance software delivery efficiency, reliability, and maintainability in modern DevOps environments.

 

13.  References

[1] GitHub Repository – Jivinlol/CICD, Original Source Code for CI/CD Pipeline.
Available at: https://github.com/Jivinlol/CICD

[2] DockerHub Repository – jlol123/cicd, Custom Docker Image for Spring Boot Application.
Available at: https://hub.docker.com/r/jlol123/cicd

[3] DockerHub Repository – jasonrivers/nagios, Official Nagios Monitoring Container Image.
Available at: https://hub.docker.com/r/jasonrivers/nagios

[4] Eclipse Temurin (OpenJDK 21) – Official Base Image used for Java Runtime.
Available at: https://hub.docker.com/_/eclipse-temurin

[5] IIT Bombay – Docker Tutorial by FOSSEE (Free and Open Source Software in Education).


14.  Acknowledgement

I would like to express my sincere gratitude to VIT SCOPE, the Course faculty Subbulakshmi T, and my mentors for providing the opportunity to design and execute this Docker and CI/CD-based project during the current semester.

Special thanks to the original creators and maintainers of the open-source repositories and Docker images used in this project, particularly the developers of Eclipse Temurin (OpenJDK), Nagios, and GitHub Actions for enabling seamless automation and monitoring.

I would also like to acknowledge the IIT Bombay Docker tutorial for its detailed, hands-on guidance that helped in understanding containerization concepts.

Finally, heartfelt thanks to my friends, classmates, and family members for their continuous support, motivation, and encouragement throughout the completion of this project.


Comments