Skip to content

Jenkins

Jenkins is an open-source automation server widely used for CI/CD pipelines.

┌─────────────────────────────────────────────────────────────────────────────┐
│ Jenkins Overview │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Jenkins Architecture │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Jenkins Master │ │ │
│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │
│ │ │ │ Scheduler │ │ Web UI │ │ Build Queue │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────────┼──────────────────┐ │ │
│ │ SSH SSH SSH │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Agent │ │ Agent │ │ Agent │ │ │
│ │ │ (Linux) │ │ (Linux) │ │ (Windows) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
│ Key Features: │
│ ✓ Open source and free │
│ ✓ Extensive plugin ecosystem │
│ ✓ Distributed builds (master/agents) │
│ ✓ Pipeline as code │
│ ✓ Strong community support │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# Docker
docker run -d -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
jenkins/jenkins:lts
# Ubuntu/Debian
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb https://pkg.jenkins.io/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt update
sudo apt install jenkins
# Start Jenkins
sudo systemctl start jenkins
sudo systemctl enable jenkins

Jenkinsfile defines the CI/CD pipeline as code.

// Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'docker.io'
APP_NAME = 'myapp'
}
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 1, unit: 'HOURS')
disableConcurrentBuilds()
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
script {
echo "Building ${APP_NAME}..."
sh 'mvn clean package'
}
}
}
stage('Test') {
steps {
script {
echo "Running tests..."
sh 'mvn test'
}
}
post {
always {
junit 'target/surefire-reports/*.xml'
publishHTML(target: [
reportDir: 'target/site',
reportFiles: 'index.html',
reportName: 'Test Report'
])
}
}
}
stage('Security Scan') {
steps {
script {
echo "Running security scan..."
sh 'trivy image ${APP_NAME}:${env.BUILD_NUMBER}'
}
}
}
stage('Build Docker Image') {
steps {
script {
sh '''
docker build -t ${APP_NAME}:${env.BUILD_NUMBER} .
docker tag ${APP_NAME}:${env.BUILD_NUMBER} ${DOCKER_REGISTRY}/${APP_NAME}:latest
'''
}
}
}
stage('Deploy to Staging') {
when {
branch 'develop'
}
steps {
script {
echo "Deploying to staging..."
sh 'kubectl apply -f k8s/staging/'
}
}
}
stage('Deploy to Production') {
when {
branch 'main'
}
steps {
input message: 'Deploy to production?', ok: 'Deploy'
script {
echo "Deploying to production..."
sh 'kubectl apply -f k8s/production/'
}
}
}
}
post {
success {
echo "Build completed successfully!"
emailext (
subject: "SUCCESS: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "Check console output at ${env.BUILD_URL}",
to: 'team@example.com'
)
}
failure {
echo "Build failed!"
emailext (
subject: "FAILURE: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "Check console output at ${env.BUILD_URL}",
to: 'team@example.com'
)
}
always {
cleanWs()
}
}
}
// Jenkinsfile (Scripted Pipeline)
node('docker') {
try {
stage('Checkout') {
checkout scm
}
stage('Build') {
sh 'mvn clean package'
}
stage('Test') {
sh 'mvn test'
junit 'target/surefire-reports/*.xml'
}
stage('Build Image') {
def image = docker.build("myapp:${env.BUILD_NUMBER}")
}
stage('Deploy') {
if (env.BRANCH_NAME == 'main') {
sh 'kubectl apply -f k8s/production/'
}
}
} catch (Exception e) {
echo "Error: ${e.message}"
currentBuild.result = 'FAILURE'
} finally {
cleanWs()
}
}
┌─────────────────────────────────────────────────────────────────────────────┐
│ Jenkins Agents (Nodes) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Agent Types │ │
│ │ │ │
│ │ Permanent Agents: │ │
│ │ • Installed on dedicated machines │ │
│ │ • Always available │ │
│ │ • Good for specialized requirements │ │
│ │ │ │
│ │ Docker Agents: │ │
│ │ • Spin up containers for builds │ │
│ │ • Isolated environment │ │
│ │ • Auto-scaling │ │
│ │ │ │
│ │ Kubernetes Agents: │ │
│ │ • Dynamic provisioning │ │
│ │ • Jenkins Kubernetes plugin│ │ • Best for cloud │ │
-native │ │
│ │ │ │
└─────────────────────────────────────────────────────────────────────────────┘
pipeline {
agent {
docker {
image 'maven:3.8.6'
label 'docker'
args '-v /root/.m2:/root/.m2'
}
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}
agent {
ovy
pipeline kubernetes {
label 'jenkins-agent'
defaultContainer 'jnlp'
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: builder
image: maven:3.8.6
command:
- cat
tty: true
- name: docker
image: docker:latest
command:
- cat
tty: true
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
volumes:
- name: docker-socket
hostPath:
path: /var/run/docker.sock
'''
}
}
stages {
stage('Build') {
container('builder') {
sh 'mvn clean package'
}
}
stage('Docker Build') {
container('docker') {
sh 'docker build -t myapp .'
}
}
}
}
// Best Practices Jenkinsfile
pipeline {
agent any
// Use environment variables
environment {
DOCKER_REGISTRY = 'registry.example.com'
}
// Shared libraries
libraries {
lib('jenkins-shared-library')
}
options {
// Keep only last 10 builds
buildDiscarder(logRotator(numToKeepStr: '10'))
// Timeout
timeout(time: 30, unit: 'MINUTES')
// Disable concurrent builds
disableConcurrentBuilds()
}
stages {
stage('Initialize') {
steps {
// Detect changes
script {
env.CHANGES = sh(script: 'git diff --name-only HEAD~1', returnStdout: true).trim()
}
}
}
stage('Build') {
steps {
sh 'make build'
}
}
stage('Test') {
steps {
sh 'make test'
}
post {
always {
junit testResults: '**/test-results/*.xml', allowEmptyResults: true
}
}
}
}
post {
always {
cleanWs()
}
}
}
Terminal window
# Build job
jenkins-cli build my-job
# Build with parameters
jenkins-cli build my-job -p VERSION=1.0.0
# Copy artifact
jenkins-cli get-artifact my-job/42/artifact.war
# List jobs
jenkins-cli list-jobs
# Trigger build
curl -X POST http://localhost:8080/job/my-job/build
# Trigger with parameters
curl -X POST http://localhost:8080/job/my-job/buildWithParameters \
-d PARAMETER=value
┌─────────────────────────────────────────────────────────────────────────────┐
│ Essential Jenkins Plugins │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Pipeline: │
│ ✓ pipeline - Pipeline as code │
│ ✓ workflow-aggregator - Workflow support │
│ ✓ blueocean - Modern UI │
│ │
│ Source Control: │
│ ✓ git - Git integration │
│ ✓ github - GitHub integration │
│ ✓ gitlab - GitLab integration │
│ │
│ Build Tools: │
│ ✓ maven-integration - Maven support │
│ ✓ gradle - Gradle support │
│ ✓ npm - NPM support │
│ │
│ Testing: │
│ ✓ junit - JUnit support │
│ ✓ testng - TestNG support │
│ ✓ cobertura - Code coverage │
│ │
│ Deployment: │
│ ✓ kubernetes - Kubernetes support │
│ ✓ docker-workflow - Docker support │
│ ✓ ansible - Ansible integration │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

In this chapter, you learned:

  • Jenkins Overview: Architecture and key features
  • Installing Jenkins: Docker, Ubuntu/Debian
  • Declarative Pipeline: Jenkinsfile structure
  • Scripted Pipeline: Groovy-based scripting
  • Agent Configuration: Permanent, Docker, Kubernetes
  • Best Practices: Environment, options, error handling
  • Jenkins CLI: Command-line interface
  • Plugins: Essential plugins for CI/CD