Skip to main content

Jenkins Fundamentals

What is Jenkins?​

Jenkins is an open-source automation server used for continuous integration (CI) and continuous delivery (CD). It enables developers to reliably build, test, and deploy software by automating parts of software development. Jenkins is written in Java and runs on various platforms.

Key Characteristics​

  • Open-source: Free and community-driven
  • Extensible: Large plugin ecosystem
  • Distributed: Master-agent architecture for scalability
  • Pipeline-as-code: Define CI/CD workflows in version control
  • Multi-language: Supports any programming language
  • Cloud-ready: Integrates with cloud platforms

CI/CD Concepts​

Continuous Integration (CI)​

CI is the practice of merging code changes into a central repository frequently, with automated testing after each commit.

Benefits:

  • Early bug detection
  • Reduced integration problems
  • Faster feedback to developers
  • Improved code quality

Continuous Delivery (CD)​

CD extends CI by automating the deployment process to production-like environments.

Benefits:

  • Reduced deployment risk
  • Faster time-to-market
  • Automated release process
  • Consistent deployments

Continuous Deployment​

Automatically deploy to production after passing tests (no manual approval).

Jenkins Architecture​

Master-Agent Architecture​

Master (Controller):

  • Manages jobs and builds
  • Schedules builds
  • Monitors agents
  • Serves web interface
  • Stores configurations

Agents:

  • Execute builds
  • Run tests
  • Deploy applications
  • Distributed across infrastructure
  • Can be on-premise or cloud

Components​

  • Jenkins Master: Central server managing orchestration
  • Agents: Remote/local machines executing jobs
  • Plugins: Extend Jenkins functionality
  • Pipeline: Define build/test/deploy workflows
  • Repository: SCM integration (Git, SVN, etc.)

Installation​

Linux Installation​

# Ubuntu/Debian
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | \
sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | \
sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins

# Start Jenkins
sudo systemctl start jenkins
sudo systemctl enable jenkins

Docker Installation​

docker run -p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:latest

Initial Setup​

  1. Access Jenkins at http://localhost:8080
  2. Get initial admin password: /var/lib/jenkins/secrets/initialAdminPassword
  3. Install suggested plugins
  4. Create admin user
  5. Configure Jenkins URL

Jenkins Pipeline Flow​

Typical Pipeline Stages​

Creating Jobs​

Freestyle Jobs​

Traditional Jenkins jobs with GUI configuration.

1. Dashboard → New Item → Freestyle Job
2. Configure source control (Git, SVN)
3. Add build triggers
4. Add build steps (shell, Maven, Gradle)
5. Add post-build actions
6. Save and build

When to use: Simple builds, quick setup, legacy systems.

Pipeline Jobs​

Define builds as code in version control.

1. Dashboard → New Item → Pipeline
2. Pipeline section:
- Definition: Pipeline script from SCM
- SCM: Git repository
- Script path: Jenkinsfile
3. Save and build

When to use: Complex workflows, CI/CD best practices, modern projects.

Jenkinsfile​

A Jenkinsfile is a text file defining the build pipeline.

Declarative Pipeline​

pipeline {
agent any

environment {
ENV_VAR = "value"
}

triggers {
githubPush()
}

options {
timeout(time: 1, unit: 'HOURS')
timestamps()
}

stages {
stage('Checkout') {
steps {
checkout scm
}
}

stage('Build') {
steps {
sh 'mvn clean package'
}
}

stage('Test') {
steps {
sh 'mvn test'
}
}

stage('Deploy') {
steps {
sh './deploy.sh'
}
}
}

post {
always {
cleanWs()
}

success {
echo 'Build succeeded!'
}

failure {
echo 'Build failed!'
}
}
}

Scripted Pipeline​

node {
stage('Checkout') {
checkout scm
}

stage('Build') {
sh 'mvn clean package'
}

stage('Test') {
sh 'mvn test'
}

try {
stage('Deploy') {
sh './deploy.sh'
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
throw e
}
}

Declarative vs Scripted:

  • Declarative: Simpler, recommended for most use cases
  • Scripted: More flexible, Groovy-based, for complex logic

Stages, Steps, and Post​

Stages​

Stages represent logical sections of a pipeline:

stages {
stage('Build') {
steps {
// Build steps
}
}

stage('Test') {
steps {
// Test steps
}
}
}

Steps​

Individual commands or operations within stages:

steps {
sh 'echo "Building application"'
sh 'npm install'
sh 'npm run build'
}

Post​

Runs after stages complete (conditionally or always):

post {
always {
// Always run
cleanWs()
}

success {
// Run on success
echo 'Deployment successful'
}

failure {
// Run on failure
emailext(
subject: "Build Failed",
body: "Build failed: ${BUILD_LOG}",
to: "team@example.com"
)
}

cleanup {
// Cleanup resources
sh 'rm -rf temp/*'
}
}

Agents​

Agents specify where pipeline runs (master or specific agent).

Agent Types​

// Any available agent
agent any

// Specific agent label
agent {
label 'linux-docker'
}

// Docker container
agent {
docker {
image 'maven:3.8-openjdk-11'
args '-v /var/run/docker.sock:/var/run/docker.sock'
}
}

// Kubernetes pod
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.8
command:
- cat
tty: true
'''
}
}

// No agent required (declarative only)
agent none

Triggers​

Triggers determine when builds start.

SCM Polling​

triggers {
// Poll Git every 5 minutes
pollSCM('*/5 * * * *')
}

Webhook Trigger​

triggers {
// GitHub webhook
githubPush()

// Generic webhook
genericWebhook(
token: 'my-secret-token'
)
}

Cron Trigger​

triggers {
// Build at 2 AM daily
cron('0 2 * * *')
}

Timer Trigger​

triggers {
// Build every hour
timerTrigger('H * * * *')
}

Upstream Trigger​

triggers {
// Trigger after another job succeeds
upstream(threshold: 'FAILURE', upstreamProjects: 'upstream-job')
}

Plugins​

Plugins extend Jenkins functionality. Essential plugins include:

PluginPurpose
GitGit repository integration
PipelinePipeline support
DockerDocker integration
KubernetesKubernetes integration
Email ExtensionAdvanced email notifications
Blue OceanModern UI
SlackSlack integration
SonarQubeCode quality analysis
ArtifactoryArtifact repository
AWSAWS integration

Installing Plugins​

  1. Manage Jenkins → Plugin Manager
  2. Search for plugin
  3. Click Install
  4. Restart Jenkins if needed

Credentials Management​

Types of Credentials​

  • Username/Password: Basic auth
  • SSH Keys: For Git over SSH
  • API Tokens: For service authentication
  • Secret File: Credential files
  • Secret Text: Encrypted strings

Using Credentials in Pipeline​

pipeline {
agent any

environment {
// Reference credentials
GIT_CREDS = credentials('github-ssh-key')
DB_PASS = credentials('db-password')
}

stages {
stage('Checkout') {
steps {
git(
url: 'git@github.com:myorg/repo.git',
credentialsId: 'github-ssh-key',
branch: 'main'
)
}
}

stage('Deploy') {
steps {
withCredentials([
string(credentialsId: 'api-key', variable: 'API_KEY'),
usernamePassword(
credentialsId: 'docker-hub',
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASS'
)
]) {
sh '''
echo $API_KEY > /tmp/api.key
docker login -u $DOCKER_USER -p $DOCKER_PASS
'''
}
}
}
}
}

Jenkins with Docker​

Running Jobs in Docker Containers​

pipeline {
agent any

stages {
stage('Build') {
agent {
docker {
image 'maven:3.8-openjdk-11'
args '-v /var/run/docker.sock:/var/run/docker.sock'
}
}

steps {
sh 'mvn clean package'
}
}

stage('Docker Image') {
steps {
sh '''
docker build -t myapp:${BUILD_NUMBER} .
docker push myregistry.azurecr.io/myapp:${BUILD_NUMBER}
'''
}
}
}
}

Running Jenkins in Docker​

docker run -d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
--name jenkins \
jenkins/jenkins:latest

Jenkins with Kubernetes​

Deploy Jenkins to Kubernetes​

# Using Helm
helm repo add jenkins https://charts.jenkins.io
helm install jenkins jenkins/jenkins -f values.yaml

Running Pipeline on Kubernetes​

pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
metadata:
labels:
jenkins: agent
spec:
serviceAccountName: jenkins
containers:
- name: maven
image: maven:3.8-openjdk-11
command: ['cat']
tty: true
- name: docker
image: docker:20.10-dind
securityContext:
privileged: true
'''
}
}

stages {
stage('Build') {
container('maven') {
steps {
sh 'mvn clean package'
}
}
}

stage('Docker Build') {
container('docker') {
steps {
sh 'docker build -t myapp:latest .'
}
}
}
}
}

Practical Exercises​

Exercise 1: Create a Simple Freestyle Job​

1. New Item → Enter name "HelloWorld" → Freestyle
2. Build section:
- Add Build Step → Execute shell
- Command: echo "Hello, Jenkins!"
3. Save
4. Click "Build Now"
5. View console output

Exercise 2: Create a Pipeline Job with Git​

pipeline {
agent any

stages {
stage('Checkout') {
steps {
checkout scm
}
}

stage('Build') {
steps {
sh 'ls -la'
}
}
}
}

Exercise 3: Create Pipeline with Docker Agent​

pipeline {
agent {
docker {
image 'node:16'
args '-v /var/run/docker.sock:/var/run/docker.sock'
}
}

stages {
stage('Setup') {
steps {
sh 'npm --version'
}
}

stage('Build') {
steps {
sh 'npm install && npm run build'
}
}

stage('Test') {
steps {
sh 'npm test'
}
}
}
}

Exercise 4: Pipeline with Environment Variables​

pipeline {
agent any

environment {
APP_NAME = 'myapp'
BUILD_VERSION = "${BUILD_NUMBER}"
DOCKER_REGISTRY = 'myregistry.azurecr.io'
}

stages {
stage('Print Vars') {
steps {
sh '''
echo "App: $APP_NAME"
echo "Version: $BUILD_VERSION"
echo "Registry: $DOCKER_REGISTRY"
'''
}
}
}
}

Exercise 5: Pipeline with Post Actions​

pipeline {
agent any

stages {
stage('Build') {
steps {
sh 'echo "Building..."'
}
}
}

post {
always {
echo 'Build completed'
}

success {
echo 'Build succeeded!'
}

failure {
echo 'Build failed!'
}

unstable {
echo 'Build is unstable'
}
}
}

Key Concepts​

  • Master-Agent: Distributed architecture for scalability
  • Pipeline: Code-based workflow definition
  • Declarative: Simplified pipeline syntax (recommended)
  • Scripted: Groovy-based pipeline (advanced)
  • Stages: Logical workflow sections
  • Post: Actions after pipeline completion
  • Agents: Execution environments
  • Triggers: Build initiation mechanisms
  • Plugins: Extensibility through community contributions
  • Credentials: Secure secrets management

Next Steps​

  • Install Jenkins locally or in Docker
  • Create first pipeline
  • Integrate with Git repository
  • Add automated tests
  • Set up artifact publishing
  • Implement deployment automation