CI/CD Pipeline Design with Jenkins, Docker and Kubernetes

DevOps 8 min readPublished 16 August 2026

Quick answer

Learn how to design a reliable CI/CD pipeline using Jenkins, Docker and Kubernetes. Explore pipeline stages, security, deployment and rollback practices.

A well-designed CI/CD pipeline converts application changes into tested, secure and deployable releases. Jenkins automates the workflow, Docker creates consistent application packages, and Kubernetes manages container deployment across a cluster.

Using these tools together is not simply a matter of writing a Jenkinsfile. A production-ready design must address source control, test quality, image tagging, secrets, deployment safety, observability and rollback. This guide explains the complete workflow and provides practical examples that DevOps engineers can adapt for real projects.

What Is a CI/CD Pipeline?

Continuous Integration, or CI, is the practice of frequently merging code into a shared repository. Every change triggers automated validation such as compilation, unit testing, static analysis and container image creation.

Continuous Delivery keeps validated releases ready for deployment. Continuous Deployment goes one step further by automatically releasing every successful change to an environment, subject to the organisation's controls.

A typical pipeline follows this sequence:

  1. A developer pushes code to Git.
  2. A webhook triggers Jenkins.
  3. Jenkins checks out the requested commit.
  4. Automated tests and quality checks run.
  5. Docker builds an immutable container image.
  6. The pipeline scans and pushes the image to a registry.
  7. Kubernetes deploys the selected image.
  8. Readiness checks confirm whether the release is healthy.
  9. Monitoring tools observe the application after deployment.

CI/CD does not remove operational control. It makes release steps consistent, repeatable and auditable.

Roles of Jenkins, Docker and Kubernetes

Each component solves a different part of the delivery process.

ToolPrimary responsibilityTypical pipeline use
JenkinsWorkflow automationCheckout, testing, approvals and deployment orchestration
DockerApplication packagingBuild a portable container image with dependencies
Container registryImage storageStore versioned images for deployment
KubernetesContainer orchestrationScheduling, scaling, health checks and rolling updates

Jenkins should coordinate tasks rather than become the permanent storage location for build artefacts. Docker images belong in a registry such as Amazon Elastic Container Registry, Azure Container Registry, Google Artifact Registry, Harbor or another approved registry.

Kubernetes then pulls the exact image selected by the pipeline. This separation makes it easier to promote one tested image across development, staging and production.

Recommended Pipeline Architecture

The pipeline should use Git as the source of truth and store its configuration with the application. In Jenkins, this usually means committing a Jenkinsfile to the repository.

A practical architecture contains:

  • A Git repository for application code and pipeline configuration
  • Jenkins controller and one or more build agents
  • Docker-capable or container-based agents
  • A private container registry
  • Separate Kubernetes namespaces or clusters for each environment
  • A secrets management system
  • Centralised logging, metrics and alerts

Avoid running builds directly on the Jenkins controller. Dedicated agents provide better isolation and prevent resource-intensive Docker builds from affecting Jenkins administration.

For larger environments, ephemeral Jenkins agents can run as Kubernetes pods. The Jenkins Kubernetes plugin can create an agent for a job and remove it after completion. Agent images should contain only the tools required by the pipeline.

Designing the Pipeline Stages

1. Checkout and Version Identification

The pipeline must check out a specific commit and assign an immutable release identifier. Do not rely only on tags such as latest, because the image behind that tag can change.

A useful tag can combine the Jenkins build number and shortened Git commit:

142-a31f82c

For stronger release traceability, Kubernetes can deploy an image by registry digest. A digest identifies the exact image content even if a human-readable tag is moved.

2. Build and Automated Testing

Run fast tests early so that failures consume the least possible time. Depending on the application, CI checks may include:

  • Dependency installation
  • Compilation
  • Unit tests
  • Code formatting or linting
  • Static application security testing
  • Software composition analysis
  • Integration tests

The test command depends on the technology stack. A Java application might use Maven or Gradle, while Node.js projects commonly use npm. Test reports should be published in Jenkins so that teams can inspect failures without searching through raw console output.

3. Docker Image Build

A Dockerfile defines the runtime package. Multi-stage builds help separate compilation tools from the final runtime image.

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm test

FROM node:22-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=build /app/src ./src
USER node
EXPOSE 3000
CMD ["node", "src/server.js"]

Pin base images appropriately and review them regularly. A smaller image can reduce download time and attack surface, but size alone does not guarantee security.

Include a .dockerignore file to exclude Git metadata, local dependencies, test output and secrets from the build context.

4. Image Security Scanning

Scan the built image before pushing or deploying it. Tools such as Trivy can detect known vulnerabilities in operating system packages and application dependencies.

trivy image --exit-code 1 --severity HIGH,CRITICAL \
  registry.example.com/team/web:142-a31f82c

A production policy should define which findings block a build, how exceptions are approved and when exceptions expire. Treating every finding in the same way can create unnecessary pipeline failures, while ignoring all findings creates avoidable risk.

5. Push to a Container Registry

Authenticate with credentials stored in Jenkins Credentials, not in the repository or Jenkinsfile. Push only after required tests and scans pass.

The registry should enforce access controls, encrypted connections, retention policies and image scanning where available. Production clusters normally require pull access, while the CI identity requires push access.

6. Deploy to Kubernetes

Kubernetes deployments support controlled rolling updates. The container name in the deployment must match the name passed to kubectl set image.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: production
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      imagePullSecrets:
        - name: registry-credentials
      containers:
        - name: web
          image: registry.example.com/team/web:initial
          ports:
            - containerPort: 3000
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 20
            periodSeconds: 20
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi

The readiness probe prevents traffic from reaching a pod until it can serve requests. The liveness probe allows Kubernetes to restart a container that has entered an unhealthy state. These probes should represent real application behaviour without depending on unrelated external services.

Resource requests help the scheduler place pods. Limits prevent one container from consuming uncontrolled resources, although CPU and memory values must be tested for the application rather than copied blindly.

Jenkins Declarative Pipeline Example

The following simplified Jenkinsfile builds, scans, pushes and deploys an image. It assumes that Docker, Trivy and kubectl are installed on the selected agent.

pipeline {
    agent { label 'docker' }

    options {
        disableConcurrentBuilds()
        timestamps()
        timeout(time: 30, unit: 'MINUTES')
    }

    environment {
        REGISTRY = 'registry.example.com'
        IMAGE = 'team/web'
        KUBE_NAMESPACE = 'production'
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
                script {
                    def commit = sh(
                        script: 'git rev-parse --short=7 HEAD',
                        returnStdout: true
                    ).trim()
                    env.IMAGE_TAG = "${env.BUILD_NUMBER}-${commit}"
                }
            }
        }

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

        stage('Build Image') {
            steps {
                sh 'docker build -t $REGISTRY/$IMAGE:$IMAGE_TAG .'
            }
        }

        stage('Scan Image') {
            steps {
                sh 'trivy image --exit-code 1 --severity HIGH,CRITICAL $REGISTRY/$IMAGE:$IMAGE_TAG'
            }
        }

        stage('Push Image') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'registry-credentials',
                    usernameVariable: 'REGISTRY_USER',
                    passwordVariable: 'REGISTRY_PASSWORD'
                )]) {
                    sh '''
                        echo "$REGISTRY_PASSWORD" | docker login \
                          --username "$REGISTRY_USER" --password-stdin "$REGISTRY"
                        docker push "$REGISTRY/$IMAGE:$IMAGE_TAG"
                        docker logout "$REGISTRY"
                    '''
                }
            }
        }

        stage('Deploy') {
            steps {
                withCredentials([file(
                    credentialsId: 'kubeconfig-production',
                    variable: 'KUBECONFIG'
                )]) {
                    sh '''
                        kubectl --kubeconfig="$KUBECONFIG" \
                          -n "$KUBE_NAMESPACE" set image deployment/web \
                          web="$REGISTRY/$IMAGE:$IMAGE_TAG"
                        kubectl --kubeconfig="$KUBECONFIG" \
                          -n "$KUBE_NAMESPACE" rollout status deployment/web \
                          --timeout=180s
                    '''
                }
            }
        }
    }

    post {
        always {
            sh 'docker image rm $REGISTRY/$IMAGE:$IMAGE_TAG || true'
            cleanWs()
        }
    }
}

In a mature setup, deployment may use Helm, Kustomize or a GitOps controller instead of directly changing the cluster from Jenkins. The correct choice depends on governance, scale and audit requirements.

Environment Promotion and Approval

Build an image once and promote the same image through development, staging and production. Rebuilding for each environment can produce different binaries or dependencies, even when the source commit is unchanged.

Environment-specific configuration should be supplied at deployment time through ConfigMaps, Secrets or an external secrets system. Do not package database passwords, API keys or environment URLs inside the image.

A common promotion flow is:

  • Automatically deploy successful main-branch builds to development
  • Run integration and acceptance tests
  • Promote the tested image digest to staging
  • Require an authorised approval for production
  • Deploy the same digest and verify the rollout

Jenkins provides an input step for manual approval, but production access should also be controlled through role-based permissions and protected credentials.

Rollback and Failure Handling

A pipeline should define failure behaviour before the first production release. If Kubernetes cannot complete the rollout, Jenkins must fail the deployment stage and alert the responsible team.

The previous Kubernetes deployment revision can be restored with:

kubectl -n production rollout undo deployment/web
kubectl -n production rollout status deployment/web --timeout=180s

Rollback is not always safe. A database migration may make the older application incompatible with the new schema. Use backward-compatible migrations, separate schema changes from destructive cleanup and test rollback procedures in non-production environments.

For high-risk systems, consider canary or blue-green deployment. These strategies require traffic management and meaningful application metrics; simply starting a second set of pods is not enough.

Security Best Practices

Secure the complete software supply chain rather than only the Kubernetes cluster.

  • Give Jenkins service accounts the minimum required permissions.
  • Use separate credentials for development and production.
  • Never print passwords, tokens or kubeconfig content in logs.
  • Rotate credentials and remove unused access.
  • Run containers as non-root where the application supports it.
  • Apply Kubernetes RBAC, NetworkPolicies and namespace isolation.
  • Scan dependencies, images and Kubernetes manifests.
  • Record image tags, digests, commits and deployment results.
  • Protect main branches with reviews and required checks.
  • Keep Jenkins, plugins, agents and base images patched.

Avoid giving a Jenkins identity unrestricted cluster-admin access. A deployment service account should normally be limited to specific resources in the target namespace.

Monitoring and Pipeline Metrics

A successful Jenkins job does not prove that users are receiving a healthy service. Monitor the application after deployment through metrics, logs and traces.

Useful delivery indicators include build duration, test failure trends, deployment frequency, failed deployment rate and recovery time. Kubernetes events and rollout status help diagnose scheduling or probe failures, while application monitoring detects errors that infrastructure checks may miss.

Jenkins should send clear notifications containing the job name, build number, commit, image identifier, environment and failure stage. Teams in Chennai, Bangalore or distributed locations can then investigate without manually reconstructing release details.

Common Design Mistakes

Frequent problems include using latest in production, embedding secrets in images, skipping readiness probes and allowing concurrent deployments to the same environment. Other mistakes are rebuilding images during promotion, granting excessive Kubernetes permissions and treating a successful pod start as complete application validation.

A reliable pipeline remains understandable. Complex scripts without version control, ownership or documentation become difficult to maintain. Start with clear stages, add controls based on risk and test the entire release and rollback process regularly.

Building Practical DevOps Skills

For DevOps roles in Indian technology companies, candidates should understand more than individual commands. Employers commonly assess Git workflows, Jenkins pipelines, Docker image design, Kubernetes deployments, Linux troubleshooting, networking, cloud services and security fundamentals.

Hands-on practice should include creating a Jenkinsfile, operating build agents, pushing to a private registry, configuring probes, diagnosing failed rollouts and implementing least-privilege access. A lab project that demonstrates these tasks provides stronger evidence of ability than memorising tool definitions.

Conclusion

Jenkins, Docker and Kubernetes form a practical CI/CD toolchain when each component has a clear responsibility. Jenkins automates validation and promotion, Docker creates immutable release artefacts, and Kubernetes performs controlled deployment and runtime management.

The most important design principles are to build once, use traceable image versions, protect credentials, verify every rollout and prepare a tested rollback method. These controls turn a basic automation script into a maintainable delivery system.

Frequently asked questions

How do Jenkins, Docker and Kubernetes work together?

Jenkins runs the automated pipeline, Docker packages the application as a container image, and Kubernetes deploys and manages that image. A container registry provides storage between the build and deployment stages.

Should Jenkins build Docker images directly on the controller?

No. Docker builds should run on dedicated or ephemeral Jenkins agents to protect controller stability and improve isolation. The controller should primarily schedule jobs, manage configuration and coordinate pipeline execution.

Why should a pipeline avoid the latest Docker tag?

The `latest` tag is mutable and does not reliably identify which application version is running. Use a unique build tag, Git commit identifier or image digest so that deployments and rollbacks remain traceable.

How should Jenkins credentials be stored?

Store registry credentials, tokens and kubeconfig files in Jenkins Credentials or an integrated secrets manager. Inject them only into the stage that needs them, restrict access and avoid printing secret values in build logs.

What is the difference between a readiness probe and a liveness probe?

A readiness probe determines whether a pod can receive traffic from a Service. A liveness probe determines whether Kubernetes should restart an unhealthy container.

Can Jenkins automatically roll back a failed Kubernetes deployment?

Yes, Jenkins can run `kubectl rollout undo` when rollout verification fails. However, automatic rollback must be designed carefully because database or API compatibility changes may prevent an older application version from working safely.

Related articles

Train with Network Rhinos

Hands-on CCNA, CCNP, AWS, Azure, DevOps and cybersecurity training in Chennai & Bangalore, with placement support. Talk to our team or attend a free demo class.