Building a CI/CD Pipeline with Docker, GitLab, Harbor, and Jenkins

Understanding CI/CD Concepts

Continuous Integration (CI) involves frequently merging code changes into a shared repository, followed by automated builds and tests to detect integration issues early.

Continuous Delivery (CD) ensures that code is always in a deployable state and can be released to production at any time with minimal manual intervention.

Continuous Deployment (CD) goes a step further by automatically deploying every change that passes the pipeline directly to production environments.

  1. Setting Up GitLab with Docker

Deploy GitLab using Docker with persistent volumes and exposed ports:

docker run -d \
  --name gitlab \
  -p 8443:443 \
  -p 9999:80 \
  -p 9998:22 \
  -v $PWD/config:/etc/gitlab \
  -v $PWD/logs:/var/log/gitlab \
  -v $PWD/data:/var/opt/gitlab \
  -v /etc/localtime:/etc/localtime \
  gitlab/gitlab-ce:latest

Access GitLab at http://<host-ip>:9999. Ensure the host has atleast 2 GB RAM (4 GB recommended for production).

To initialize a local project and push to GitLab:

git init
git config --global user.email "user@example.com"
git config --global user.name "YourName"
git remote add origin http://192.168.1.11:9999/root/java-demo.git
git add .
git commit -m "Initial commit"
git push origin master

  1. Deploying Harbor as a Private Registry

Install Docker Compose first, then configure and launch Harbor:

tar zxvf harbor-offline-installer-v1.9.1.tgz
cd harbor
# Edit harbor.yml: set hostname to 192.168.1.10
./prepare
./install.sh

After building an image locally, tag it for Harbor:

docker tag my-app:1.0 192.168.1.10/library/my-app:1.0

  1. Configuring Jenkins for CI/CD

Since Harbor uses HTTP (not HTTPS), configure Docker to trust the insecure registry:

{
  "registry-mirrors": ["http://f1361db2.m.daocloud.io"],
  "insecure-registries": ["192.168.1.10"]
}

Restart Docker: systemctl restart docker.

Install JDK and Maven on the host:

tar zxvf jdk-8u45-linux-x64.tar.gz
mv jdk1.8.0_45 /usr/local/jdk
tar zxf apache-maven-3.5.0-bin.tar.gz
mv apache-maven-3.5.0 /usr/local/maven

Run Jenkins container with necessary volume mounts:

docker run -d --name jenkins \
  -p 8080:8080 -p 50000:50000 -u root \
  -v /opt/jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /usr/bin/docker:/usr/bin/docker \
  -v /usr/local/maven:/usr/local/maven \
  -v /usr/local/jdk:/usr/local/jdk \
  -v /etc/localtime:/etc/localtime \
  jenkins/jenkins:lts

Install required plugins (Pipeline, Git) and create a new pipeline job with a string parameter named Branch (default: master).

Pipeline Script

#!/usr/bin/env groovy

def REGISTRY = "192.168.1.10"
def PROJECT = "library"
def APP_NAME = "java-demo"
def IMAGE_TAG = "${REGISTRY}/${PROJECT}/${APP_NAME}:${params.Branch}-${BUILD_NUMBER}"
def GIT_REPO = "http://192.168.1.11:9999/root/java-demo.git"
def HARBOR_CRED = "harbor-credentials-id"
def GIT_CRED = "git-credentials-id"

pipeline {
    agent any
    stages {
        stage('Clone Repository') {
            steps {
                checkout([$class: 'GitSCM',
                    branches: [[name: "*/${params.Branch}"]],
                    doGenerateSubmoduleConfigurations: false,
                    extensions: [],
                    userRemoteConfigs: [[
                        credentialsId: GIT_CRED,
                        url: GIT_REPO
                    ]]
                ])
            }
        }

        stage('Build Application') {
            steps {
                sh '''
                    export JAVA_HOME=/usr/local/jdk
                    export PATH=$JAVA_HOME/bin:/usr/local/maven/bin:$PATH
                    mvn clean package -DskipTests
                '''
            }
        }

        stage('Build and Push Image') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: HARBOR_CRED,
                    passwordVariable: 'HARBOR_PASS',
                    usernameVariable: 'HARBOR_USER'
                )]) {
                    sh """
                        cat > Dockerfile <<eof .="" add="" build="" container="" docker="" echo="" eof="" from="" label="" login="" maintainer="dev-team" push="" rm="" run="" sh="" stage="" steps="" stop="" target="" true=""></eof>

Before running the pipeline, add two credentials in Jenkins:

  • A username/password credential for GitLab (used as GIT_CRED)
  • A username/password credential for Harbor (used as HARBOR_CRED)

Each pipeline stage logs detailed output for debugging and validation.

Tags: docker gitlab harbor Jenkins CI/CD

Posted on Sun, 11 Oct 2026 16:13:23 +0000 by php1999