Skip to content

Repository files navigation

DevOps ArgoCD Jenkins App

License: MIT Docker Pulls Build Status

A complete CI/CD pipeline demonstration using Jenkins, ArgoCD, Docker, and Kubernetes

This repository showcases a production-ready DevOps workflow with automated builds, containerization, and GitOps-based deployments.

πŸ“‹ Table of Contents


🎯 Overview

This project implements a complete CI/CD pipeline that:

  • βœ… Automatically builds Docker images on code commits
  • βœ… Pushes images to DockerHub registry
  • βœ… Updates Kubernetes manifests with new image tags
  • βœ… Deploys applications using GitOps principles via ArgoCD
  • βœ… Supports multiple environments (staging, production)
  • βœ… Includes monitoring with Prometheus and Grafana

Tech Stack:

  • CI/CD: Jenkins
  • Containerization: Docker
  • Orchestration: Kubernetes
  • GitOps: ArgoCD
  • Registry: DockerHub
  • Monitoring: Prometheus, Grafana, Alertmanager

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   GitHub    │─────▢│   Jenkins   │────▢│  DockerHub  β”‚
β”‚  (Source)   β”‚      β”‚   (Build)   β”‚      β”‚  (Registry) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β”‚ Update Manifest
                            β–Ό
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚   GitHub    β”‚
                     β”‚ (GitOps)    β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β”‚ Sync
                            β–Ό
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚   ArgoCD    │─────▢│ Kubernetes  β”‚
                     β”‚   (Deploy)  β”‚      β”‚  (Runtime)  β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚ Monitoring  β”‚
                     β”‚ (Prom/Graf) β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Workflow:

  1. Developer pushes code to GitHub
  2. Jenkins detects changes via webhook
  3. Jenkins builds Docker image and pushes to DockerHub
  4. Jenkins updates Kubernetes manifest with new image tag
  5. ArgoCD detects manifest changes
  6. ArgoCD syncs and deploys to Kubernetes cluster
  7. Monitoring stack tracks application health

βœ… Prerequisites

Before starting, ensure you have:

Required Tools

  • Docker (v24.0+) - Install Docker
  • Kubernetes Cluster (v1.26+) - Options:
    • Minikube (local testing)
    • K3s/K3d (lightweight)
    • EKS/GKE/AKS (cloud)
    • OpenShift (optional)
  • kubectl (v1.26+) - Install kubectl
  • Git (v2.34+)

Accounts Needed

  • GitHub account with repository access
  • DockerHub account (free tier works)
  • Basic understanding of Docker, Kubernetes, and CI/CD concepts

System Requirements

  • Minimum: 4GB RAM, 2 CPU cores, 20GB disk space
  • Recommended: 8GB RAM, 4 CPU cores, 50GB disk space

Optional Tools

  • Helm (v3.0+) - For advanced deployments
  • ArgoCD CLI - For command-line operations
  • ngrok - For local webhook testing

πŸš€ Quick Start

# Clone the repository
git clone https://github.com/eknathdj/devops-argocd-jenkins-app.git
cd devops-sample-app

# Build Docker image locally (optional test)
docker build -t devops-sample-app:local .

# Run locally to test
docker run -p 8080:8080 devops-sample-app:local

# Verify application
curl http://localhost:8080/health

For full CI/CD setup, continue to Detailed Setup.


πŸ“– Detailed Setup

1. Jenkins Setup

Step 1.1: Install Jenkins with Docker

Option A: Using Docker Compose (Recommended)

Create jenkins/docker-compose.yml:

version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    user: root
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - JAVA_OPTS=-Djenkins.install.runSetupWizard=false
    command: >
      bash -c "
        apt-get update &&
        apt-get install -y docker.io curl git &&
        git config --global --add safe.directory '*' &&
        /usr/local/bin/jenkins.sh
      "

volumes:
  jenkins_home:

Start Jenkins:

docker-compose -f jenkins/docker-compose.yml up -d

Option B: Using Docker CLI

docker run -d \
  --name jenkins \
  -p 8080:8080 -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --user root \
  jenkins/jenkins:lts

# Install dependencies inside Jenkins container
docker exec -it jenkins bash
apt-get update && apt-get install -y docker.io curl git
git config --global --add safe.directory '*'
exit
docker restart jenkins

Step 1.2: Initial Jenkins Configuration

  1. Get Initial Admin Password:
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
  1. Access Jenkins:
    • Open browser: http://localhost:8080
    • Paste the admin password
    • Click "Install suggested plugins"
    • Create your admin user

Step 1.3: Install Required Jenkins Plugins

Go to Manage Jenkins β†’ Plugins β†’ Available plugins

Install these plugins:

  • βœ… Git Plugin (git operations)
  • βœ… Pipeline (pipeline support)
  • βœ… Docker Pipeline (Docker integration)
  • βœ… Credentials Binding (secure credential handling)
  • βœ… Workspace Cleanup (cleanWs support)

Click "Install without restart" and wait for completion.

Step 1.4: Configure Jenkins Credentials

a) GitHub Credentials (Personal Access Token)
  1. Generate GitHub PAT:

    • Go to GitHub β†’ Settings β†’ Developer settings β†’ Personal access tokens β†’ Tokens (classic)
    • Click "Generate new token (classic)"
    • Name: Jenkins CI
    • Expiration: 90 days or No expiration
    • Select scopes:
      • βœ… repo (Full control of repositories)
      • βœ… workflow (Update GitHub Action workflows)
    • Click "Generate token"
    • ⚠️ Copy the token immediately (you won't see it again!)
  2. Add to Jenkins:

    • Go to Jenkins β†’ Manage Jenkins β†’ Credentials β†’ System β†’ Global credentials
    • Click "Add Credentials"
    • Kind: Username with password
    • Username: eknathdj (your GitHub username)
    • Password: Paste your GitHub PAT
    • ID: github-creds
    • Description: GitHub Personal Access Token
    • Click "Create"
b) DockerHub Credentials
  1. Add to Jenkins:
    • Same path: Manage Jenkins β†’ Credentials β†’ System β†’ Global credentials
    • Click "Add Credentials"
    • Kind: Username with password
    • Username: Your DockerHub username
    • Password: Your DockerHub password or access token
    • ID: dockerhub-creds
    • Description: DockerHub Registry Credentials
    • Click "Create"

Step 1.5: Create Jenkins Pipeline

  1. Create New Pipeline:

    • Click "New Item"
    • Name: sample-app-pipeline
    • Select "Pipeline"
    • Click "OK"
  2. Configure Pipeline:

    • Description: CI/CD Pipeline for DevOps Sample App

    • Build Triggers:

      • βœ… Check "GitHub hook trigger for GITScm polling"
    • Pipeline Definition:

      • Select "Pipeline script from SCM"
      • SCM: Git
      • Repository URL: https://github.com/eknathdj/devops-argocd-jenkins-app
      • Credentials: Select github-creds
      • Branch: */main
      • Script Path: Jenkinsfile
    • Additional Behaviours:

      • Add "Wipe out repository & force clone" (optional, for clean builds)
  3. Click "Save"


2. GitHub Configuration

Step 2.1: Configure Webhook

  1. Go to your GitHub repository: https://github.com/eknathdj/devops-sample-app
  2. Click Settings β†’ Webhooks β†’ Add webhook
  3. Configure:
    • Payload URL: http://<YOUR_JENKINS_IP>:8080/github-webhook/
      • Replace <YOUR_JENKINS_IP> with your Jenkins server IP
      • For local testing with public access, use ngrok:
        ngrok http 8080
        # Use the ngrok URL: https://xxxx.ngrok.io/github-webhook/
    • Content type: application/json
    • Events: Select "Just the push event"
    • Active: βœ… Checked
  4. Click "Add webhook"

Step 2.2: Verify Repository Structure

Ensure your repository has this structure:

devops-sample-app/
β”œβ”€β”€ .gitignore                          # Git ignore rules
β”œβ”€β”€ Dockerfile                          # Docker build instructions
β”œβ”€β”€ Jenkinsfile                         # CI/CD pipeline definition
β”œβ”€β”€ package.json                        # Node.js dependencies
β”œβ”€β”€ package-lock.json                   # Lockfile for dependencies
β”œβ”€β”€ server.js                           # Main application file
β”œβ”€β”€ healthcheck.js                      # Health check endpoint
β”œβ”€β”€ prometheus-alerts.yaml              # Prometheus alerting rules
β”œβ”€β”€ devops-pipeline-dashboard.json      # Grafana dashboard JSON
β”œβ”€β”€ SECURITY.md                         # Security policy
β”œβ”€β”€ README.md                           # This file
β”œβ”€β”€ argocd/
β”‚   β”œβ”€β”€ production-application.yaml     # ArgoCD app for production
β”‚   └── staging-application.yaml        # ArgoCD app for staging
β”œβ”€β”€ argocd-servicemonitor.yaml          # ArgoCD service monitor
β”œβ”€β”€ environments/
β”‚   β”œβ”€β”€ production/
β”‚   β”‚   β”œβ”€β”€ deployment.yaml             # K8s deployment for production
β”‚   β”‚   β”œβ”€β”€ service.yaml                # K8s service for production
β”‚   β”‚   β”œβ”€β”€ namespace.yaml              # K8s namespace for production
β”‚   β”‚   └── kustomization.yaml          # Kustomize config for production
β”‚   └── staging/
β”‚       β”œβ”€β”€ deployment.yaml             # K8s deployment for staging
β”‚       β”œβ”€β”€ service.yaml                # K8s service for staging
β”‚       β”œβ”€β”€ namespace.yaml              # K8s namespace for staging
β”‚       β”œβ”€β”€ kustomization.yaml          # Kustomize config for staging
β”‚       └── servicemonitor.yaml         # Service monitor for staging
β”œβ”€β”€ jenkins/
β”‚   β”œβ”€β”€ docker-compose.yml              # Jenkins Docker Compose
β”‚   └── init-scripts/                   # Jenkins initialization scripts
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ install-argocd.sh               # ArgoCD installation script
β”‚   β”œβ”€β”€ install-monitoring.sh           # Monitoring stack installation
β”‚   └── test-pipeline.sh                # Pipeline testing script
└── jenkins-servicemonitor.yaml         # Jenkins service monitor

3. DockerHub Configuration

Step 3.1: Create DockerHub Repository

  1. Log in to DockerHub
  2. Click "Create Repository"
  3. Configure:
    • Name: devops-sample-app
    • Visibility: Public (or Private if preferred)
    • Description: Sample DevOps application
  4. Click "Create"

Your image will be: <username>/devops-sample-app

Step 3.2: Update Jenkinsfile

Edit the DOCKER_IMAGE environment variable in your Jenkinsfile:

environment {
    DOCKER_IMAGE = "your-dockerhub-username/devops-sample-app"
    // ... rest of config
}

4. ArgoCD Setup

Step 4.1: Install ArgoCD

Use the provided installation script:

chmod +x scripts/install-argocd.sh
./scripts/install-argocd.sh

Or manually:

# Create namespace
kubectl create namespace argocd

# Install ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Wait for pods to be ready
kubectl wait --for=condition=available --timeout=300s deployment/argocd-server -n argocd

Step 4.2: Access ArgoCD UI

Option A: Port Forward (Local Access)

kubectl port-forward svc/argocd-server -n argocd 8081:443

Access at: https://localhost:8081

Option B: LoadBalancer (Cloud)

kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
kubectl get svc argocd-server -n argocd

Step 4.3: Get ArgoCD Admin Password

# For ArgoCD 2.0+
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

# Username: admin
# Password: (output from above command)

Step 4.4: Install ArgoCD CLI (Optional)

# Linux
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x /usr/local/bin/argocd

# macOS
brew install argocd

# Login via CLI
argocd login localhost:8081 --username admin --password <password> --insecure

Step 4.5: Create ArgoCD Application

Use the pre-configured application manifests:

# For staging
kubectl apply -f argocd/staging-application.yaml

# For production
kubectl apply -f argocd/production-application.yaml

Or create manually via UI/CLI as described in the original setup.


5. Monitoring Setup

Step 5.1: Install Monitoring Stack

Use the provided installation script:

chmod +x scripts/install-monitoring.sh
./scripts/install-monitoring.sh

Or manually:

# Install Prometheus and Grafana
kubectl create namespace monitoring

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
  -n monitoring

# Access Grafana
kubectl port-forward svc/prometheus-grafana -n monitoring 3000:80
# Default: admin / prom-operator

Step 5.2: Import Dashboard

  1. Access Grafana at http://localhost:3000
  2. Go to Dashboards β†’ Import
  3. Upload devops-pipeline-dashboard.json
  4. Select the Prometheus data source

Step 5.3: Configure ServiceMonitors

Apply the service monitors:

kubectl apply -f jenkins-servicemonitor.yaml
kubectl apply -f argocd-servicemonitor.yaml
kubectl apply -f environments/staging/servicemonitor.yaml

πŸ”„ Pipeline Workflow

What Happens When You Push Code?

  1. Trigger: Push to GitHub β†’ Webhook notifies Jenkins
  2. Setup: Jenkins configures Git and cleans workspace
  3. Checkout: Clone repository
  4. Build: Create Docker image tagged with build number
  5. Push: Upload image to DockerHub
  6. Update: Modify Kubernetes manifest with new image tag
  7. Commit: Push manifest changes back to GitHub
  8. Deploy: ArgoCD detects changes and syncs to Kubernetes

Manual Trigger

To manually trigger a build:

# In Jenkins UI: Click "Build Now" on your pipeline
# Or via CLI:
curl -X POST http://localhost:8080/job/sample-app-pipeline/build \
  --user admin:<your-jenkins-token>

Monitor Deployment

# Watch ArgoCD sync status
argocd app get sample-app-staging --refresh

# Watch Kubernetes pods
kubectl get pods -n staging -w

# Check application logs
kubectl logs -f deployment/sample-app -n staging

# Get service endpoint
kubectl get svc -n staging

πŸ”§ Troubleshooting

Common Issues and Solutions

1. Jenkins: "fatal: not in a git directory"

Cause: Git ownership/permission issue

Solution:

# Inside Jenkins container
docker exec -it jenkins bash
git config --global --add safe.directory '*'
exit
docker restart jenkins

2. Jenkins: "Permission denied" when pushing to GitHub (403 error)

Cause: GitHub credentials invalid or expired

Solution:

  • Generate new GitHub Personal Access Token (PAT)
  • Update github-creds in Jenkins with new PAT
  • Ensure PAT has repo and workflow scopes

3. Jenkins: "Cannot connect to Docker daemon"

Cause: Docker socket not mounted or permission issue

Solution:

# Ensure socket is mounted
docker run -v /var/run/docker.sock:/var/run/docker.sock ...

# Or give Jenkins user permission
docker exec -it jenkins bash
chmod 666 /var/run/docker.sock

4. ArgoCD: Application stuck in "OutOfSync"

Cause: Manifest changes not detected or sync policy issue

Solution:

# Force refresh
argocd app get sample-app-staging --refresh

# Manual sync
argocd app sync sample-app-staging

# Check diff
argocd app diff sample-app-staging

5. Kubernetes: ImagePullBackOff

Cause: Image not found in registry or auth issue

Solution:

# Verify image exists in DockerHub
# Check image name in deployment.yaml matches exactly

# For private repos, create imagePullSecret
kubectl create secret docker-registry dockerhub-secret \
  --docker-server=https://index.docker.io/v1/ \
  --docker-username=<username> \
  --docker-password=<password> \
  -n staging

# Add to deployment.yaml:
# imagePullSecrets:
#   - name: dockerhub-secret

6. Jenkins: Build fails at "Update ArgoCD Manifest" stage

Cause: File path incorrect or sed command issue

Solution:

# Verify file exists
ls -la environments/staging/deployment.yaml

# Test sed command locally
sed -i 's|image: .*|image: new-image:tag|g' environments/staging/deployment.yaml

Debug Commands

# Jenkins logs
docker logs jenkins -f

# ArgoCD logs
kubectl logs -f deployment/argocd-server -n argocd

# Application logs
kubectl logs -f deployment/sample-app -n staging

# Describe pod for details
kubectl describe pod <pod-name> -n staging

# Check events
kubectl get events -n staging --sort-by='.lastTimestamp'

🎯 Best Practices

Security

  1. Rotate Credentials Regularly

    • GitHub PATs: Rotate every 90 days
    • DockerHub tokens: Use access tokens instead of passwords
    • Jenkins credentials: Audit quarterly
  2. Use Secrets Management

    # Store sensitive data in Kubernetes secrets
    kubectl create secret generic app-secrets \
      --from-literal=api-key=xxx \
      -n staging
  3. Enable RBAC

    • Restrict Jenkins service account permissions
    • Use least-privilege principle in Kubernetes

Pipeline Optimization

  1. Use Build Caching

    # In Dockerfile, order layers by change frequency
    COPY package.json .
    RUN npm install
    COPY . .
  2. Parallel Stages

    parallel {
        stage('Test') { ... }
        stage('Security Scan') { ... }
    }
  3. Conditional Deployment

    when {
        branch 'main'
        expression { currentBuild.result == 'SUCCESS' }
    }

GitOps Best Practices

  1. Separate Config from Code

    • Keep manifests in environments/ directory
    • Use different branches for environments (optional)
  2. Version Everything

    • Always use specific image tags (never :latest)
    • Tag format: v1.0.0-${BUILD_NUMBER}
  3. Environment Parity

    • Use same base manifests with overlays
    • Consider using Kustomize or Helm

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit changes: git commit -m 'Add amazing feature'
  4. Push to branch: git push origin feature/amazing-feature
  5. Open a Pull Request

Development Workflow

# Clone your fork
git clone https://github.com/eknathdj/devops-argocd-jenkins-app.git

# Add upstream remote
git remote add upstream https://github.com/eknathdj/devops-argocd-jenkins-app.git

# Create feature branch
git checkout -b feature/my-feature

# Make changes and test locally
docker build -t test:local .
docker run -p 8080:8080 test:local

# Commit and push
git add .
git commit -m "Description of changes"
git push origin feature/my-feature

πŸ“š Additional Resources

Documentation

Tutorials

Community


πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ‘€ Author

Eknath DJ


πŸ™ Acknowledgments

  • Jenkins community for excellent CI/CD tooling
  • ArgoCD team for GitOps innovation
  • Kubernetes community for container orchestration
  • Prometheus and Grafana teams for monitoring excellence
  • All contributors to this project

πŸ“ž Support

If you encounter issues:

  1. Check the Troubleshooting section
  2. Search existing GitHub Issues
  3. Create a new issue with:
    • Clear description of the problem
    • Steps to reproduce
    • Error logs
    • Environment details (OS, versions, etc.)

⭐ If this project helped you, please give it a star!


Last Updated: October 2025

About

No description, website, or topics provided.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages