DEV Community

Michelle
Michelle

Posted on

30-Day Cloud & DevOps Challenge: Day 8 — Jenkins: my First CI/CD Pipeline

Yesterday, I had all three containers running with Docker Compose; frontend, backend, and PostgreSQL.

But there was still one manual step: every time I changed code, I had to rebuild and restart containers manually.

Today, I fixed that forever.

I installed Jenkins — an automation server that watches my GitHub repository and runs tasks automatically when code changes. This is the heart of CI/CD (Continuous Integration/Continuous Deployment).


First: What is Jenkins?

In one sentence: Jenkins is a tool that automatically runs tasks when your code changes.

The Problem Jenkins Solves

Without Jenkins (where I was):

  1. Write code
  2. git push
  3. Manually run docker-compose up --build
  4. Wait
  5. Repeat for every change

With Jenkins:

  1. Write code
  2. git push
  3. Jenkins AUTOMATICALLY builds and deploys
  4. Done!

Analogy

Without Jenkins With Jenkins
You bake bread from scratch every morning Bread machine bakes automatically when you add ingredients
Manual, repetitive, error-prone Automatic, consistent, reliable

Step 1: Running Jenkins in Docker

Since my entire stack is already containerized, running Jenkins in Docker made perfect sense.

Creating the Jenkins Docker Compose File

cd ~/Desktop/Production-Ready-Microservices-Platform
mkdir jenkins
cd jenkins
nano docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

The docker-compose.yml for Jenkins

version: '3.8'

services:
  jenkins:
    image: jenkins/jenkins:lts
    container_name: jenkins
    restart: always
    ports:
      - "8081:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DOCKER_HOST=unix:///var/run/docker.sock

volumes:
  jenkins_home:
Enter fullscreen mode Exit fullscreen mode

Understanding the Configuration

Line What it does Why it matters
image: jenkins/jenkins:lts Uses the Long-Term Support version Stable, reliable
ports: - "8081:8080" Maps host port 8081 → container port 8080 Access Jenkins at localhost:8081
volumes: - jenkins_home:/var/jenkins_home Persists Jenkins data Jobs, settings survive container restarts
volumes: - /var/run/docker.sock:/var/run/docker.sock Mounts Docker socket Jenkins can run Docker commands!
DOCKER_HOST=unix:///var/run/docker.sock Tells Jenkins where Docker is Allows building images inside Jenkins

Starting Jenkins

sudo docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

What I saw:

[+] Running 2/2
 ✔ Network jenkins_default     Created
 ✔ Container jenkins           Started
Enter fullscreen mode Exit fullscreen mode

Step 2: Accessing Jenkins Web Interface

Check Jenkins is Running

sudo docker ps
Enter fullscreen mode Exit fullscreen mode

Output:

CONTAINER ID   IMAGE                 COMMAND   STATUS         PORTS
xxxxxx         jenkins/jenkins:lts   ...       Up ...         0.0.0.0:8081->8080/tcp
Enter fullscreen mode Exit fullscreen mode

Open Jenkins

In your browser: http://localhost:8081


Step 3: Unlocking Jenkins

Jenkins requires an initial admin password.

Get the Password

sudo docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
Enter fullscreen mode Exit fullscreen mode

Output: A long string of letters and numbers (copy this!)

Paste the Password

  1. On the Jenkins web page, paste the password
  2. Click "Continue"

Step 4: Installing Plugins

Jenkins asked which plugins to install. I chose "Install suggested plugins"

What are plugins? Extensions that add features to Jenkins:

  • Git integration
  • Docker pipeline
  • Blue Ocean (pretty UI)
  • Many more

Step 5: Creating Admin User

After plugins installed, I created my admin account:

Field What I entered
Username admin
Password (created a strong password)
Full name My name
Email My email

Click "Save and Continue"


Step 6: Jenkins is Ready!

After confirming the URL (default is fine), I clicked "Start using Jenkins"

I saw the Jenkins dashboard!


Step 7: My First Pipeline Job

Creating a New Job

  1. Click "New Item" on the left menu
  2. Enter name: my-first-pipeline
  3. Select "Pipeline"
  4. Click OK

Writing the Pipeline Script

In the "Pipeline" section, I selected "Pipeline script" and added:

pipeline {
    agent any

    stages {
        stage('Hello') {
            steps {
                echo 'Hello from Jenkins!'
            }
        }

        stage('Date') {
            steps {
                sh 'date'
            }
        }

        stage('Who Am I') {
            steps {
                sh 'whoami'
            }
        }

        stage('Docker Version') {
            steps {
                sh 'docker --version'
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

What This Pipeline Does

Stage What it does Output example
Hello Prints a greeting Hello from Jenkins!
Date Runs date command Tue Apr 28 14:30:00 EAT 2026
Who Am I Shows user Jenkins runs as root (or jenkins)
Docker Version Checks Docker is available Docker version 28.5.2

Running the Pipeline

  1. Click "Save"
  2. Click "Build Now" on the left menu
  3. Click on build #1
  4. Click "Console Output"

What I saw:

[Pipeline] Start of Pipeline
[Pipeline] stage
[Pipeline] { (Hello)
[Pipeline] echo
Hello from Jenkins!
[Pipeline] }
[Pipeline] stage
[Pipeline] { (Date)
[Pipeline] sh
+ date
Tue Apr 29 10:30:00 EAT 2026
[Pipeline] }
[Pipeline] stage
[Pipeline] { (Docker Version)
[Pipeline] sh
+ docker --version
Docker version 28.5.2, build 9cc6dea35e
[Pipeline] }
[Pipeline] End of Pipeline
Finished: SUCCESS
Enter fullscreen mode Exit fullscreen mode

It worked! Jenkins successfully ran my pipeline!


Jenkins vs Docker Compose (Understanding the Difference)

Tool What it does When to use
Docker Compose Runs multiple containers together Starting your app locally
Jenkins Automates tasks when code changes CI/CD, automatic builds, testing

They work TOGETHER:

You push code → Jenkins sees it → Jenkins runs Docker Compose → Your app updates
Enter fullscreen mode Exit fullscreen mode

Issues I Ran Into (And Fixed)

Issue 1: Docker Pull Timeout

Error:

dial tcp: lookup registry-1.docker.io: i/o timeout
Enter fullscreen mode Exit fullscreen mode

Cause: DNS configuration issue with Docker.

Fix:

# Create Docker daemon config
sudo nano /etc/docker/daemon.json

# Add DNS servers
{
  "dns": ["8.8.8.8", "1.1.1.1"]
}

# Restart Docker
sudo systemctl restart docker
Enter fullscreen mode Exit fullscreen mode

Issue 2: Port Already in Use

Error:

Bind for 0.0.0.0:8080 failed: port is already allocated
Enter fullscreen mode Exit fullscreen mode

Cause: Something else was using port 8080 (maybe another Jenkins or web server).

Fix: Used port 8081 instead of 8080.

Issue 3: Jenkins Container Not Starting

Fix: Check logs:

sudo docker logs jenkins
Enter fullscreen mode Exit fullscreen mode

Docker Commands for Jenkins

Command What it does
sudo docker-compose up -d Start Jenkins in background
sudo docker-compose down Stop Jenkins
sudo docker logs jenkins View Jenkins logs
sudo docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword Get admin password

Pipeline Syntax Basics

Groovy Element What it does
pipeline { } Wraps the entire pipeline
agent any Run on any available agent
stages { } Contains all stages
stage('name') { } A named step in the pipeline
steps { } Contains the actual commands
echo 'text' Print text to console
sh 'command' Run a shell command

Key Takeaways

  1. Jenkins automates repetitive tasks — No more manual builds
  2. CI/CD = Continuous Integration/Continuous Deployment — Automate from code push to deployment
  3. Jenkins runs in Docker too — Consistent with our containerized stack
  4. Plugins extend Jenkins — Git, Docker, Slack, etc.
  5. Pipeline as Code — Your build process lives in code, not click-ops

Resources

Let's Connect!

Have you used Jenkins before? What CI/CD tool do you prefer — Jenkins, GitHub Actions, GitLab CI, or something else?

Drop a comment or connect on LinkedIn. Let's learn together!

Top comments (0)