CI/CD with Jenkins Pipelines and Blue Ocean: A Practical Setup Guide

Continuous DeliveryContinuous IntegrationDevOps

YOUR COSMETIC CARE STARTS HERE

Find the Best Cosmetic Hospitals

Trusted • Curated • Easy

Looking for the right place for a cosmetic procedure? Explore top cosmetic hospitals in one place and choose with confidence.

“Small steps lead to big changes — today is a perfect day to begin.”

Explore Cosmetic Hospitals Compare hospitals, services & options quickly.

✓ Shortlist providers • ✓ Review options • ✓ Take the next step with confidence

This article is based on a post originally published by R. Moorman at Moor Interactive (moori.nl), describing their team’s hands-on evaluation of Jenkins Blue Ocean and Pipelines.

Why Jenkins Pipelines and Blue Ocean?

Mature engineering teams tend to iterate constantly on their CI/CD workflows. Jenkins has long been a staple of that process, but its classic UI and job-configuration model can become unwieldy as project count grows. Cloud-native alternatives like Travis CI and Drone gained popularity in part because they store build configuration alongside source code in Git — something Jenkins historically made difficult.

Two Jenkins features close that gap significantly:

  • Jenkins Pipelines — lets you define your entire build, test, and deployment process as code in a Jenkinsfile committed to your repository.
  • Blue Ocean — a plugin that rethinks the Jenkins user experience, surfacing pipeline status, stage results, and test data with minimal navigation.

“Blue Ocean is a project that rethinks the user experience of Jenkins, modelling and presenting the process of software delivery by surfacing information that’s important to development teams with as few clicks as possible.”

The sections below walk through spinning up Jenkins Blue Ocean with Docker Compose, writing a declarative Jenkinsfile, and using key Pipeline features such as Docker agents, conditional stages, and post actions.

Running Jenkins Blue Ocean with Docker Compose

Containerising Jenkins keeps your host clean and makes the setup reproducible. You need three files: a Dockerfile, a docker-compose.yaml, and a docker.conf that exposes the Docker socket so Jenkins can spin up agent containers.

Dockerfile

Start from the official Blue Ocean image and copy in the Docker daemon configuration:

FROM jenkinsci/blueocean:latest
MAINTAINER R. Moorman <rob@moori.nl>
USER root
COPY docker.conf /etc/init.d/dockerCode language: HTML, XML (xml)

docker-compose.yaml

Mount the Docker socket so Jenkins can create sibling containers on the host, and persist Jenkins home to a local directory:

version: '2'
services:
  jenkins:
    build: .
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sockCode language: JavaScript (javascript)

docker.conf

Expose the Docker daemon on TCP as well as the Unix socket so the Jenkins Docker plugin can reach it:

DOCKER_OPTS="-H tcp://0.0.0.0:4243 -H unix:///var/run/docker.sock --tls=false"Code language: JavaScript (javascript)

With all three files in the same directory, start the stack:

docker-compose up

Jenkins will be available at http://localhost:8080/. Complete the initial setup wizard, then navigate to the Blue Ocean view via the sidebar.

Jenkins login screen after installation
Jenkins login screen after installation

Writing Your First Declarative Jenkinsfile

After switching to the Blue Ocean view you can create a new Pipeline and point it at a source repository. Blue Ocean will look for a Jenkinsfile at the repository root. You can also use the built-in visual Pipeline editor for quick experiments, but writing the Jenkinsfile by hand gives you full version-control history and the most flexibility.

The following example is based on a Python project. It checks out source code, runs the flake8 linter, converts results to JUnit XML format, and publishes them so Blue Ocean can display them as test results. The full example repository is available at https://github.com/robmoorman/jenkins-blueocean.

pipeline {
  agent {
    docker 'python:3.6.1'
  }
  stages {
    stage('Install dependencies') {
      steps {
        sh 'pip install -r requirements.txt'
      }
    }
    stage('Test') {
      steps {
        sh 'flake8 src/ --exit-zero --output-file flake8-output.txt'
        sh 'flake8_junit flake8-output.txt flake8-output.xml'
      }
    }
  }
  post {
    always {
      junit 'flake8-output.xml'
    }
    failure {
      echo 'Failed!'
    }
    success {
      echo 'Done!'
    }
  }
}Code language: PHP (php)
Test results displayed in the Jenkins Blue Ocean UI
Test results from the Jenkinsfile rendered in Blue Ocean

Key Pipeline Concepts Explained

Agents

The agent directive tells Jenkins where and how to run a pipeline or an individual stage. Specifying a Docker image as the agent is especially clean: Jenkins pulls the image, runs your steps inside the container, then discards it. This mirrors the approach used by Travis CI and Drone, so teams familiar with those platforms adapt quickly.

You can define different agents per stage, which makes it straightforward to compile in one environment and deploy from another — all within the same Jenkinsfile.

Stages and Steps

Splitting your build into named stages and steps serves two purposes:

  • Visibility — Blue Ocean renders each stage as a column in its pipeline view, making it immediately obvious where a build failed.
  • Control flow — when a step fails, the pipeline halts and subsequent steps are skipped. You can also attach post blocks to individual stages (for example, always publishing coverage reports after the test stage, regardless of pass/fail).

Conditional Steps with when

The when directive lets you gate a stage on branch name, environment variable, or other conditions. This is particularly useful for deployment stages that should only run on specific branches:

stage('Deploy') {
  when {
    branch 'develop'
  }
  steps {
    sh 'sh ./etc/deploy_test.sh'
  }
}Code language: JavaScript (javascript)

Combining branch conditions with pull-request detection keeps a single Jenkinsfile as the authoritative source of truth for the entire delivery process — from feature branch lint checks through to production deployment.

Post Actions and Notifications

The post block supports conditional sections including always, success, failure, unstable, and changed. Common uses include:

  • Publishing JUnit test results (junit step)
  • Sending Slack notifications on build failure
  • Archiving build artefacts
  • Triggering downstream pipelines

Note that at the time this was written (early 2017, around the first public Blue Ocean release), not all Jenkins plugins had been updated to render correctly within the Blue Ocean UI. The classic Jenkins view remained fully compatible, so plugin incompatibility was an inconvenience rather than a blocker. Plugin compatibility has continued to improve since then — check the Blue Ocean compatibility matrix for current status.

A more complex failing pipeline visualised in Blue Ocean
A more complex Pipeline execution in Blue Ocean, showing a failing stage

Conclusion

Jenkins Pipelines, with declarative Jenkinsfiles and Docker agents, offer a flexible and version-controlled approach to CI/CD that competes directly with cloud-native platforms. Storing pipeline logic in the repository itself — rather than in Jenkins job configuration — addresses one of the longest-standing pain points of traditional Jenkins setups.

Blue Ocean addresses the usability gap with a modern, stage-oriented interface that makes pipeline status easy to understand at a glance. Plugin ecosystem maturity was a real limitation at the time of Blue Ocean’s initial release, but it should not be treated as a dealbreaker given the pace of development in the Jenkins ecosystem.

If you are evaluating whether to migrate from a cloud CI platform back to self-hosted Jenkins, or simply looking to modernise an existing Jenkins setup, starting with a Dockerised Blue Ocean instance and declarative Pipelines is a low-risk way to assess the workflow before committing fully.

Next steps: Explore shared libraries to make pipeline steps reusable across repositories, and look at the parallel directive for running independent stages concurrently to cut build times.

0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x