Isolated Docker builder
Jenkins talks to a dedicated Docker-in-Docker daemon over TLS rather than receiving TestServer's host Docker socket.
CI/CD & Platform Delivery Case Study
This project builds a complete delivery path for a small Java application: test it, package it, build an immutable container, security-scan it, publish it to a protected registry and deploy it to K3s with health verification and automatic rollback.
The Challenge
Building an image is the easy part. The useful engineering work is in controlling what is allowed to move forward, keeping credentials out of source control, proving each hand-off and making failure recoverable.
The goal was therefore not simply to create a Jenkins job. It was to build a traceable delivery system where a source commit can reach Kubernetes only after tests, packaging and a vulnerability gate have passed, and where a bad deployment returns automatically to the last working image.
Delivery Flow
Each stage produces evidence before the next stage is allowed to run.
Gradle compiles, tests and archives the Java application.
An isolated Docker-in-Docker builder creates the release image.
Trivy blocks HIGH or CRITICAL findings before publication.
The approved image is pushed to the private registry and rolled out to K3s.
Security Controls
Jenkins talks to a dedicated Docker-in-Docker daemon over TLS rather than receiving TestServer's host Docker socket.
Trivy 0.72.0 scans the image for HIGH and CRITICAL vulnerabilities and returns a failing exit code when policy is breached.
Jenkins uses a publishing service account while K3s uses a separate runtime pull identity. Registry access is also firewall-restricted.
Jenkins deploys through a forced SSH command that can invoke only the root-owned Homelab Defender deployment script, not a general shell.
Failure Was Part of the Test
Jenkins build 13 completed testing, containerisation, security scanning, registry publication and the Kubernetes rollout. The first service-level health request then received a transient connection reset. The deployment script treated that as a failed release and automatically restored the previous working image.
The health check was then improved to retry safely. Build 14 repeated the complete pipeline, passed the Trivy gate with zero HIGH/CRITICAL findings, published the immutable image and deployed it successfully. Kubernetes rolled out the new pod and the service health check returnedok on the first retry cycle.
Release Evidence
First complete hands-off source-to-Kubernetes release.
Trivy gate passed before the image was allowed into the registry.
The Kubernetes ClusterIP service returned a healthy application response.
A failed post-deployment verification restores the previous image automatically.
Engineering Outcome
The finished pipeline is more than CI. It creates a controlled release chain from GitHub through Gradle, Docker and Trivy into an authenticated registry and finally K3s. The release is not considered successful until the workload has rolled out and the application health endpoint has been verified through the Kubernetes Service.
The project also keeps the Kubernetes baseline, deployment script, rollback procedure, beginner documentation and a living glossary in Git so the implementation remains understandable and reproducible.