cd /news/developer-tools/jenkins-ci-cd-pipeline-for-a-dockeri… · home topics developer-tools article
[ARTICLE · art-11028] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Jenkins CI/CD Pipeline for a Dockerized Node.js Application: Manual Trigger vs Automatic Trigger Using GitHub Webhooks

This article provides a step-by-step guide on building a CI/CD pipeline for a Dockerized Node.js application using Jenkins. It explains the transition from a manual deployment process, where a Jenkins job must be triggered by clicking "Build Now," to a fully automated system using GitHub webhooks that automatically triggers builds and deployments upon code pushes. The guide also covers essential setup steps, including installing Docker, granting Jenkins Docker permissions, and configuring GitHub authentication with personal access tokens.

read8 min views24 publishedMay 23, 2026

Have you ever pushed code to GitHub and wished your application could automatically build and deploy itself without logging into a server or clicking a button in Jenkins? In this article, you'll learn how to build a complete CI/CD pipeline for a Dockerized Node.js application using Jenkins, starting with manual deployments and progressing to fully automated deployments using GitHub webhooks.

We will cover:

  • Creating a Jenkins pipeline
  • Building a Docker image
  • Deploying a container
  • Triggering builds manually
  • Triggering builds automatically
  • GitHub Personal Access Tokens
  • Fine-grained vs Classic Tokens
  • Jenkins credentials
  • GitHub webhooks
  • Required Jenkins plugins
  • Common errors and troubleshooting The goal is to understand not only how to configure everything but also why each component is needed.

Node.js Application Repo URL-

[https://github.com/omkarsharma2821/Node.js-App-Deploy-Github-Action]

Architecture Overview #

The complete flow looks like this:

Developer
    |
    | Git Push
    v
GitHub Repository
    |
    | Webhook
    v
Jenkins
    |
    | Build Docker Image
    v
Docker
    |
    | Run Container
    v
Application Running

Without webhooks:

Developer
    |
    | Git Push
    v
GitHub Repository

Jenkins Build Now (Manual Trigger)
    |
    v
Build and Deploy

With webhooks:

Developer
    |
    | Git Push
    v
GitHub Repository
    |
    v
Webhook
    |
    v
Jenkins
    |
    v
Build and Deploy Automatically

Prerequisites #

Before starting, ensure you have:

  • Ubuntu Server
  • Jenkins installed
  • Docker installed
  • Git installed
  • GitHub repository
  • Node.js application with Dockerfile Verify installations:
jenkins --version
docker --version
git --version

Installing Docker on Jenkins Server #

Install Docker:

sudo apt update
sudo apt install docker.io -y

Enable Docker:

sudo systemctl enable docker
sudo systemctl start docker

Verify:

docker --version

Allow Jenkins to Use Docker #

By default Jenkins cannot execute Docker commands.

Add Jenkins user to Docker group:

sudo usermod -aG docker jenkins

Restart Jenkins:

sudo systemctl restart jenkins

Verify:

sudo su - jenkins
docker ps

If Docker works without sudo, Jenkins is ready.

Creating the Pipeline #

Initially we created a Jenkins pipeline that manually clones the repository.

Example:

pipeline {
    agent any

    stages {

        stage('Clone Repository') {
            steps {
                sh '''
                    mkdir -p devops
                    cd devops
                    rm -rf Node.js-App-Deploy-Github-Action
                    git clone -b main https://github.com/username/repository.git
                '''
            }
        }

        stage('Build Image') {
            steps {
                sh '''
                    cd devops/Node.js-App-Deploy-Github-Action
                    docker build -t node-app .
                '''
            }
        }

        stage('Deploy') {
            steps {
                sh '''
                    docker run -d -p 8000:8080 node-app
                '''
            }
        }
    }
}

This works, but every deployment requires manually clicking:

Build Now

Problem with Multiple Deployments #

Suppose the application is already running.

Running:

docker run -d -p 8000:8080 node-app

again will fail because port 8000 is already occupied.

Error:

Bind for 0.0.0.0:8000 failed

Better Deployment Approach #

Before starting a new container, remove the old one.

docker rm -f node-app-container || true

Then start a new container:

docker run -d --name node-app-container -p 8000:8080 node-app

Understanding docker rm -f node-app-container || true #

Let's break it down.

docker rm #

Removes a container.

docker rm node-app-container

Works only if container is stopped.

-f

Force remove.

docker rm -f node-app-container

This:

  • Stops container
  • Removes container

||

OR operator.

Syntax:

command1 || command2

If command1 fails, command2 executes.

true

Always returns success.

true

Exit code:

0

Final Meaning

docker rm -f node-app-container || true

If container exists:

Remove it

If container doesn't exist:

Ignore error and continue

This prevents Jenkins from failing.

Manual Triggering #

The simplest approach is manual execution.

Navigate to:

Jenkins Job
|
└── Build Now

Advantages:

  • Easy to understand Good for learning

Disadvantages:Requires human intervention

Not real CI/CD

Automatic Triggering #

The goal of CI/CD is:

Code Push
    |
    v
Automatic Build
    |
    v
Automatic Deployment

This is where GitHub webhooks come into play.

Required Jenkins Plugins #

Install the following Jenkins plugins before configuring the CI/CD pipeline:

1. Git Plugin

  • Enables Jenkins to interact with Git repositories.
  • Allows Jenkins to clone repositories, fetch changes, and checkout specific branches.
  • Required for integrating Jenkins with GitHub repositories.

2. GitHub Plugin

  • Provides integration between Jenkins and GitHub.
  • Allows Jenkins to communicate with GitHub repositories and services.
  • Supports GitHub-related features within Jenkins.

3. GitHub Integration Plugin

  • Enables GitHub webhook support.
  • Allows Jenkins to automatically trigger builds when code is pushed to GitHub.
  • Essential for implementing automated CI/CD workflows.

4. Pipeline Plugin

  • Enables support for Jenkins Pipelines.
  • Allows execution of Jenkinsfiles written in Declarative or Scripted Pipeline syntax.
  • Required for defining CI/CD workflows as code.

5. Credentials Plugin

  • Provides secure storage for sensitive information.

  • Allows storing:

  • GitHub Personal Access Tokens (PATs)

  • Usernames and passwords

  • SSH keys

  • API tokens

  • Prevents hardcoding secrets in Jenkins jobs and pipelines.

GitHub Authentication #

When Jenkins needs to access a GitHub repository, authentication requirements depend on the repository type.

Public Repository

  • Can typically be cloned without authentication.

Example:

git clone https://github.com/username/repository.git

Private Repository

  • Requires authentication.
  • GitHub no longer supports account passwords for Git operations.
  • A Personal Access Token (PAT) must be used instead of a password.

Why Use a Personal Access Token (PAT)?

  • More secure than passwords.
  • Allows granular permission control.
  • Can be revoked without affecting your GitHub account password.
  • Recommended by GitHub for all Git operations requiring authentication.

Classic Personal Access Token #

Older token type.

Advantages:

  • Simple Easy to configure

Disadvantages:Broad permissions

Less secure

Example scopes:

repo
workflow
admin:repo_hook

Fine-Grained Personal Access Token #

Newer and recommended approach.

Advantages:

  • Repository-level access
  • Better security
  • Granular permissions Example:
Repository Access:
Only selected repositories

Permissions:

Contents: Read and Write
Metadata: Read
Webhooks: Read and Write

Fine-Grained vs Classic Token #

Feature Fine-Grained Classic
Security High Lower
Repository Scope Specific Broad
Permission Control Granular Broad
Recommended Yes Legacy

For modern projects, prefer Fine-Grained tokens.

Adding GitHub Token to Jenkins #

Navigate to:

Manage Jenkins
|
Credentials

Select:

Global Credentials

Choose:

Add Credentials

Kind:

Username with Password

Example:

Username: GitHub Username
Password: Personal Access Token

ID:

github-creds

Save.

Pipeline Script vs Pipeline Script from SCM #

Many beginners get confused here.

Pipeline Script #

Pipeline stored inside Jenkins UI.

Example:

pipeline {
    agent any
}

Advantages:

Quick setup

Disadvantages:Not version controlled

Difficult to maintain

Pipeline Script from SCM #

Pipeline stored in GitHub repository.

Repository structure:

project/
|
|-- Dockerfile
|-- package.json
|-- app.js
|-- Jenkinsfile

Jenkins automatically downloads Jenkinsfile.

Advantages:

  • Version controlled
  • Industry standard
  • Easier maintenance Recommended approach.

Configuring Pipeline from SCM #

Create Jenkins job.

Select:

Pipeline

Under Definition:

Pipeline script from SCM

SCM:

Git

Repository URL:

https://github.com/username/repository.git

Branch:

*/main

Script Path:

Jenkinsfile

Save.

Creating GitHub Webhook #

Navigate to:

GitHub Repository
|
Settings
|
Webhooks
|
Add Webhook

Payload URL:

http://JENKINS_PUBLIC_IP:8080/github-webhook/

Content Type:

application/json

Event:

Just the push event

Save webhook.

Configuring Jenkins Trigger #

Open job configuration.

Under Build Triggers:

Select:

GitHub hook trigger for GITScm polling

Save.

Testing the Webhook #

Push code:

git add .
git commit -m "testing webhook"
git push origin main

Expected flow:

GitHub Push
    |
    v
Webhook
    |
    v
Jenkins
    |
    v
Pipeline Starts

No manual click required.

Common Troubleshooting #

Webhook Returns 404 #

Cause:

Wrong webhook URL

Correct:

http://SERVER-IP:8080/github-webhook/

Webhook Returns 403 #

Cause:

Authentication or security issue

Verify:

  • GitHub plugin
  • GitHub integration plugin

Webhook Returns 200 But Build Doesn't Start #

Common cause:

Pipeline Script instead of Pipeline Script from SCM

or

Repository mapping issue

Dockerfile Not Found #

Example:

unable to evaluate symlinks in Dockerfile path

Cause:

Wrong working directory.

Check:

pwd
ls -la

Verify Dockerfile location.

Permission Denied While Running Docker #

Cause:

Jenkins not in docker group

Fix:

sudo usermod -aG docker jenkins
sudo systemctl restart jenkins

Final Jenkinsfile #

pipeline {
    agent any

    stages {

        stage('Build Image') {
            steps {
                sh '''
                    docker build -t node-app .
                '''
            }
        }

        stage('Deploy') {
            steps {
                sh '''
                    docker rm -f node-app-container || true
                    docker run -d --name node-app-container -p 8000:8080 node-app
                '''
            }
        }
    }
}

Conclusion #

A Jenkins pipeline can be triggered manually or automatically. Manual triggering is useful for learning and testing, but real CI/CD begins when code pushes automatically trigger builds and deployments.

The recommended production approach is:

  • Store the Jenkinsfile in GitHub.
  • Use Pipeline Script from SCM.
  • Configure GitHub credentials using a Personal Access Token.
  • Enable GitHub webhook integration.
  • Use Docker for packaging and deployment.
  • Remove old containers before deploying new versions. With this setup, every code push automatically builds a Docker image, deploys a fresh container, and updates the application without requiring any manual intervention.

✍️ Author: Omkar Sharma

📬 Feel free to connect on LinkedIn or explore more on GitHub

── more in #developer-tools 4 stories · sorted by recency
── more on @jenkins 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/jenkins-ci-cd-pipeli…] indexed:0 read:8min 2026-05-23 ·