Building an End-to-End CI/CD Pipeline with Spring Boot, Jenkins, Kubernetes & Security Scans
Source: Dev.to
Why I Built This Project
I’ve worked with CI/CD concepts and tools before, but there was always a gap between knowing the tools and building a complete system.
Most tutorials stop at “Pipeline executed successfully”, while real CI/CD systems involve:
- Versioning strategies
- Webhooks
- Code quality gates
- Security scanning
- Kubernetes rollouts
- Failures, restarts, and extensive debugging
I decided to build a true end‑to‑end CI/CD pipeline, starting from a Git push and ending with a fully deployed, secure, observable Spring Boot application running on Kubernetes. This blog documents what I built, what broke, how I fixed it, and the lessons learned.
Pipeline Overview
| Layer | Technology |
|---|---|
| Application | Spring Boot |
| Versioning | Maven + /release API |
| SCM | GitHub |
| CI/CD | Jenkins (Pipeline as Code) |
| Code Quality | SonarQube |
| Exposure | Ngrok |
| Containers | Docker |
| Security | Trivy |
| Orchestration | Kubernetes |
| Database | MongoDB |
| Notifications | Jenkins Mailer |
The pipeline runs locally but behaves like a production system:
Git push → automatic Jenkins trigger
→ Maven build & tests
→ Application versioning with /release endpoint
→ Docker image build (immutable)
→ SonarQube code quality gates
→ Trivy image security scanning
→ Kubernetes deployment & rollout
→ Email notifications
→ MongoDB‑backed persistence
GitHub Push & Jenkins Trigger
- A developer pushes code to GitHub.
- A webhook (exposed via Ngrok) triggers the Jenkins pipeline automatically—no manual start required.
- Jenkins clones the repository and runs the build.
Maven Build & Tests
mvn clean test
Ensures:
- The code compiles.
- Unit tests pass.
- The build is deployable before proceeding.
SonarQube Quality Gates
- Jenkins sends the analysis report to SonarQube.
- The pipeline waits for the Quality Gate result.
- If the gate fails, the build stops, enforcing engineering standards automatically.
Docker Image Build (Multi‑stage)
A multi‑stage Dockerfile is used:
- Build stage – contains Maven and all build dependencies.
- Runtime stage – contains only the JRE and the compiled JAR.
Result: a smaller, more secure production image.
Security Scanning with Trivy
Before pushing the image to the registry, Trivy scans it:
trivy image
- Detects Critical and High vulnerabilities.
- The pipeline can be configured to fail based on severity, ensuring vulnerable images never reach deployment.
Kubernetes Deployment & Rollout
After all checks pass:
docker push /:${BUILD_NUMBER}
kubectl apply -f deployment.yaml
kubectl rollout status deployment/
Jenkins Container Issues & Solutions
| Problem | Solution |
|---|---|
Jenkins runs inside a Docker container but needs to build Docker images, causing permission issues with /var/run/docker.sock. | - Mount the host Docker socket into the Jenkins container (-v /var/run/docker.sock:/var/run/docker.sock).- Add the docker group inside the Jenkins image and add the jenkins user to that group. |
Jenkins (container) could not reach the Kubernetes API server on a Windows host using 127.0.0.1. | Run the Jenkins container with --add-host=localhost:host-gateway to map the container’s localhost to the host gateway, allowing communication with the KIND cluster. |
Kubernetes does not trigger a new rollout when the deployment still references the :latest tag, even if the image changes. | Implement dynamic image tagging: replace an IMAGE_PLACEHOLDER in deployment.yaml with a unique version ${BUILD_NUMBER}. This guarantees a rollout on every change, deterministic rollbacks, and traceable image versions. |
/release Endpoint
The Spring Boot application exposes a /release endpoint that returns:
- Application version
- Jenkins build number
- Runtime environment metadata
This makes it easy to verify which build is running inside a pod directly from the application.
Custom Jenkins Docker Image
A custom Jenkins image is built with the following tools pre‑installed:
- Maven
- Docker CLI
- Kubectl
Benefits:
- Reproducibility across environments.
- Faster onboarding for new team members.
- Consistent tool versions.
Lessons Learned
- Shift‑left security: Trivy identified critical CVEs (e.g., Tomcat RCE) before deployment.
- Network boundaries matter: Managing communication between Jenkins, SonarQube, Kubernetes, and Docker was the biggest challenge.
- Event‑driven pipelines: Removing manual triggers and relying on GitHub webhooks turned the pipeline into true CI/CD.
- Automation builds trust: Understanding how systems talk to each other and handling failures systematically elevates DevOps from scripts to engineering.
References
- GitHub repository:
- LinkedIn profile: