Skip to content

DevOps Projects Portfolio

Overview

This section showcases practical DevOps project implementations, templates, and real-world examples. Each project includes complete code, documentation, and deployment instructions.


Project Categories

CI/CD Pipeline Projects

Project Technology Complexity Description
Multi-Environment Deployment Azure DevOps + Docker Intermediate Complete pipeline with dev/staging/prod
Microservices Pipeline Jenkins + Kubernetes Advanced Service mesh deployment
GitOps Workflow GitHub Actions + ArgoCD Intermediate Git-driven deployments
Serverless Pipeline AWS CodePipeline + Lambda Intermediate Function deployment automation

Infrastructure as Code

Project Technology Complexity Description
Cloud Infrastructure Terraform + AWS Intermediate VPC, EC2, RDS, security groups
Kubernetes Cluster Terraform + EKS Advanced Managed Kubernetes setup
Multi-Cloud Network Terraform + Azure + AWS Advanced Hybrid cloud connectivity
Monitoring Stack Terraform + Prometheus Intermediate Complete observability setup

Container Orchestration

Project Technology Complexity Description
Docker Microservices Docker Compose Beginner Multi-service application
Kubernetes Application K8s manifests + Helm Intermediate Production-ready deployment
Service Mesh Istio + Kubernetes Advanced Traffic management and security
Container CI/CD GitHub Actions + Docker Intermediate Automated container builds

Project Overview

A full-stack web application with complete DevOps pipeline demonstrating modern development practices.

Project Structure:
├── app/                    # Application code
│   ├── backend/           # Node.js API
│   ├── frontend/          # React SPA
│   └── database/          # PostgreSQL schemas
├── infrastructure/        # Infrastructure as Code
│   ├── terraform/         # Cloud resources
│   └── kubernetes/        # K8s manifests
├── pipelines/             # CI/CD pipelines
│   ├── azure-pipelines.yml
│   └── github-actions/
├── monitoring/            # Observability
│   ├── prometheus/
│   └── grafana/
├── docs/                  # Documentation
└── scripts/               # Utility scripts

Technology Stack

Component Technology Purpose
Frontend React + TypeScript User interface
Backend Node.js + Express REST API
Database PostgreSQL Data persistence
Infrastructure Terraform + AWS Cloud resources
Containerization Docker + Kubernetes Application packaging
CI/CD Azure DevOps Automated deployment
Monitoring Prometheus + Grafana Observability

Infrastructure Setup

Terraform Configuration

# infrastructure/terraform/main.tf
terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

# VPC Configuration
module "vpc" {
  source = "./modules/vpc"

  name = "${var.project_name}-vpc"
  cidr = var.vpc_cidr

  azs             = var.availability_zones
  private_subnets = var.private_subnets
  public_subnets  = var.public_subnets

  enable_nat_gateway = true
  single_nat_gateway = true
}

# ECS Cluster
module "ecs" {
  source = "./modules/ecs"

  cluster_name = "${var.project_name}-cluster"

  # Container insights for monitoring
  container_insights = true
}

# RDS Database
module "rds" {
  source = "./modules/rds"

  identifier = "${var.project_name}-db"

  engine         = "postgres"
  engine_version = "14.7"
  instance_class = "db.t3.micro"

  db_name  = var.db_name
  username = var.db_username
  password = var.db_password
  port     = 5432

  vpc_security_group_ids = [module.security.sg_database_id]
  subnet_ids             = module.vpc.private_subnets
}

# Application Load Balancer
module "alb" {
  source = "./modules/alb"

  name = "${var.project_name}-alb"

  vpc_id          = module.vpc.vpc_id
  subnets         = module.vpc.public_subnets
  security_groups = [module.security.sg_alb_id]

  target_groups = [
    {
      name             = "${var.project_name}-api"
      backend_protocol = "HTTP"
      backend_port     = 3000
      target_type      = "ip"
    },
    {
      name             = "${var.project_name}-web"
      backend_protocol = "HTTP"
      backend_port     = 80
      target_type      = "ip"
    }
  ]
}

Kubernetes Manifests

# infrastructure/kubernetes/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
      - name: web
        image: myregistry/web-app:latest
        ports:
        - containerPort: 80
        env:
        - name: API_URL
          value: "http://api-service:3000"
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
        livenessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web-app
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: web-tls
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

CI/CD Pipeline

Azure DevOps Pipeline

# pipelines/azure-pipelines.yml
trigger:
  branches:
    include:
    - main
    - develop

pr:
  branches:
    include:
    - main

stages:
- stage: Build
  jobs:
  - job: BuildAndTest
    pool:
      vmImage: 'ubuntu-latest'

    steps:
    - checkout: self
      submodules: true

    # Backend build
    - task: NodeTool@0
      inputs:
        versionSpec: '18.x'

    - script: |
        cd app/backend
        npm ci
        npm run build
        npm test
      displayName: 'Build and test backend'

    # Frontend build
    - script: |
        cd app/frontend
        npm ci
        npm run build
        npm run test:ci
      displayName: 'Build and test frontend'

    # Docker build
    - task: Docker@2
      inputs:
        containerRegistry: 'my-registry'
        repository: 'web-app'
        command: 'buildAndPush'
        Dockerfile: 'app/Dockerfile'
        tags: |
          $(Build.BuildId)
          latest

    # Publish artifacts
    - publish: $(System.DefaultWorkingDirectory)/infrastructure
      artifact: infrastructure

- stage: DeployDev
  dependsOn: Build
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
  jobs:
  - deployment: Deploy
    environment: 'dev'
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: infrastructure

          - task: KubernetesManifest@0
            inputs:
              action: 'deploy'
              kubernetesServiceConnection: 'dev-cluster'
              manifests: |
                $(Pipeline.Workspace)/infrastructure/kubernetes/deployment.yml
                $(Pipeline.Workspace)/infrastructure/kubernetes/service.yml
              containers: |
                myregistry/web-app:$(Build.BuildId)

- stage: DeployStaging
  dependsOn: DeployDev
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: Deploy
    environment: 'staging'
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: infrastructure

          - task: KubernetesManifest@0
            inputs:
              action: 'deploy'
              kubernetesServiceConnection: 'staging-cluster'
              manifests: |
                $(Pipeline.Workspace)/infrastructure/kubernetes/deployment.yml
                $(Pipeline.Workspace)/infrastructure/kubernetes/service.yml
              containers: |
                myregistry/web-app:$(Build.BuildId)

- stage: DeployProd
  dependsOn: DeployStaging
  jobs:
  - deployment: Deploy
    environment: 'prod'
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: infrastructure

          - task: KubernetesManifest@0
            inputs:
              action: 'deploy'
              kubernetesServiceConnection: 'prod-cluster'
              manifests: |
                $(Pipeline.Workspace)/infrastructure/kubernetes/deployment.yml
                $(Pipeline.Workspace)/infrastructure/kubernetes/service.yml
              containers: |
                myregistry/web-app:$(Build.BuildId)

Monitoring Setup

Prometheus Configuration

# monitoring/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

scrape_configs:
  - job_name: 'kubernetes-apiservers'
    kubernetes_sd_configs:
    - role: endpoints
    scheme: https
    tls_config:
      ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
    - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
      action: keep
      regex: default;kubernetes;https

  - job_name: 'kubernetes-service-endpoints'
    kubernetes_sd_configs:
    - role: endpoints
    relabel_configs:
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
      action: keep
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
      action: replace
      target_label: __scheme__
      regex: (https?)
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      action: replace
      target_label: __metrics_path__
      regex: (.+)
    - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: ([^:]+)(?::\d+)?;(\d+)
      replacement: $1:$2

  - job_name: 'web-app'
    static_configs:
      - targets: ['web-app:80']
    scrape_interval: 5s

Grafana Dashboard

{
  "dashboard": {
    "title": "Web Application Dashboard",
    "tags": ["web-app", "kubernetes"],
    "timezone": "browser",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total[5m])",
            "legendFormat": "Requests/sec"
          }
        ]
      },
      {
        "title": "Response Time",
        "type": "graph",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
            "legendFormat": "95th percentile"
          }
        ]
      },
      {
        "title": "Error Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "rate(http_requests_total{status=~\"5..\"}[5m]) / rate(http_requests_total[5m]) * 100",
            "legendFormat": "Error %"
          }
        ]
      }
    ]
  }
}

Application Code Examples

Backend API (Node.js)

// app/backend/src/server.js
const express = require('express');
const { Pool } = require('pg');
const app = express();

const pool = new Pool({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
});

app.use(express.json());

// Health check endpoint
app.get('/health', async (req, res) => {
  try {
    await pool.query('SELECT 1');
    res.json({ status: 'healthy', database: 'connected' });
  } catch (error) {
    res.status(503).json({ status: 'unhealthy', database: 'disconnected' });
  }
});

// API endpoints
app.get('/api/users', async (req, res) => {
  try {
    const result = await pool.query('SELECT id, name, email FROM users');
    res.json(result.rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.post('/api/users', async (req, res) => {
  const { name, email } = req.body;
  try {
    const result = await pool.query(
      'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *',
      [name, email]
    );
    res.status(201).json(result.rows[0]);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

module.exports = app;

Frontend (React)

// app/frontend/src/App.js
import React, { useState, useEffect } from 'react';
import './App.css';

function App() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetchUsers();
  }, []);

  const fetchUsers = async () => {
    try {
      const response = await fetch('/api/users');
      if (!response.ok) {
        throw new Error('Failed to fetch users');
      }
      const data = await response.json();
      setUsers(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  const addUser = async (userData) => {
    try {
      const response = await fetch('/api/users', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(userData),
      });
      if (!response.ok) {
        throw new Error('Failed to add user');
      }
      const newUser = await response.json();
      setUsers([...users, newUser]);
    } catch (err) {
      setError(err.message);
    }
  };

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div className="App">
      <header className="App-header">
        <h1>User Management System</h1>
      </header>
      <main>
        <UserList users={users} />
        <AddUserForm onAddUser={addUser} />
      </main>
    </div>
  );
}

export default App;

Docker Configuration

Multi-Stage Dockerfile

# app/Dockerfile
# Build stage
FROM node:18-alpine AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./
RUN npm ci --only=production

# Copy source code
COPY . .

# Build application
RUN npm run build

# Production stage
FROM node:18-alpine AS production

WORKDIR /app

# Install production dependencies only
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

# Copy built application
COPY --from=builder /app/dist ./dist

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

USER nextjs

EXPOSE 3000

CMD ["npm", "start"]

Docker Compose

# docker-compose.yml
version: '3.8'

services:
  web:
    build: ./frontend
    ports:
      - "3000:3000"
    environment:
      - REACT_APP_API_URL=http://api:3001
    depends_on:
      - api

  api:
    build: ./backend
    ports:
      - "3001:3001"
    environment:
      - DB_HOST=db
      - DB_PORT=5432
      - DB_NAME=myapp
      - DB_USER=myapp
      - DB_PASSWORD=password
    depends_on:
      - db

  db:
    image: postgres:14
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=myapp
      - POSTGRES_PASSWORD=password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  postgres_data:

Deployment Instructions

Local Development

# Clone repository
git clone https://github.com/your-org/web-app.git
cd web-app

# Start development environment
docker-compose up -d

# Access application
# Frontend: http://localhost:3000
# API: http://localhost:3001
# Database: localhost:5432

Production Deployment

# Build and push Docker images
docker build -t myregistry/web-app:latest ./app
docker push myregistry/web-app:latest

# Deploy to Kubernetes
kubectl apply -f infrastructure/kubernetes/

# Check deployment status
kubectl get pods
kubectl get services
kubectl get ingress

Testing Strategy

Unit Tests

// app/backend/test/user.test.js
const request = require('supertest');
const app = require('../src/server');

describe('User API', () => {
  it('should get all users', async () => {
    const response = await request(app)
      .get('/api/users')
      .expect(200);

    expect(Array.isArray(response.body)).toBe(true);
  });

  it('should create a new user', async () => {
    const userData = {
      name: 'John Doe',
      email: 'john@example.com'
    };

    const response = await request(app)
      .post('/api/users')
      .send(userData)
      .expect(201);

    expect(response.body).toHaveProperty('id');
    expect(response.body.name).toBe(userData.name);
    expect(response.body.email).toBe(userData.email);
  });
});

Integration Tests

# Pipeline integration test
- script: |
    # Start test environment
    docker-compose -f docker-compose.test.yml up -d

    # Wait for services
    sleep 30

    # Run integration tests
    npm run test:integration

    # Cleanup
    docker-compose -f docker-compose.test.yml down
  displayName: 'Run integration tests'

Security Considerations

Container Security

# Secure Dockerfile practices
FROM node:18-alpine

# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# Install dependencies before copying source
COPY package*.json ./
RUN npm ci --only=production

# Copy source with appropriate permissions
COPY --chown=nextjs:nodejs . .

USER nextjs

EXPOSE 3000

Infrastructure Security

# Security groups
resource "aws_security_group" "web" {
  name_prefix = "web-sg"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "database" {
  name_prefix = "db-sg"

  ingress {
    from_port       = 5432
    to_port         = 5432
    protocol        = "tcp"
    security_groups = [aws_security_group.web.id]
  }
}

Performance Optimization

Database Optimization

-- Database indexes
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created_at ON users(created_at);

-- Query optimization
EXPLAIN ANALYZE
SELECT u.name, u.email, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2023-01-01'
GROUP BY u.id, u.name, u.email
ORDER BY order_count DESC;

Caching Strategy

// Redis caching
const redis = require('redis');
const client = redis.createClient();

app.get('/api/users/:id', async (req, res) => {
  const { id } = req.params;
  const cacheKey = `user:${id}`;

  // Check cache first
  client.get(cacheKey, async (err, cachedUser) => {
    if (cachedUser) {
      return res.json(JSON.parse(cachedUser));
    }

    // Fetch from database
    try {
      const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]);
      const user = result.rows[0];

      // Cache for 5 minutes
      client.setex(cacheKey, 300, JSON.stringify(user));

      res.json(user);
    } catch (error) {
      res.status(500).json({ error: error.message });
    }
  });
});

Troubleshooting Guide

Common Issues

Issue Symptom Solution
Container fails to start CrashLoopBackOff Check logs: kubectl logs <pod-name>
Database connection fails Connection timeout Verify security groups and VPC configuration
High memory usage OOM kills Increase resource limits in deployment
Slow response times >500ms latency Check database queries and add caching
Pipeline failures Build/test errors Review pipeline logs and fix code issues

Monitoring Commands

# Kubernetes debugging
kubectl get pods
kubectl describe pod <pod-name>
kubectl logs <pod-name> -f

# Database monitoring
docker exec -it db psql -U myapp -d myapp
SELECT * FROM pg_stat_activity;

# Application metrics
curl http://localhost:3000/health
curl http://localhost:9090/metrics

Project Templates

Quick Start Template

# Create new project from template
npx create-react-app frontend
npx express-generator backend
mkdir infrastructure monitoring docs

# Initialize Git
git init
git add .
git commit -m "Initial project structure"

Microservices Template

microservices-app/
├── services/
│   ├── auth-service/
│   ├── user-service/
│   ├── order-service/
│   └── notification-service/
├── infrastructure/
│   ├── docker-compose.yml
│   ├── kubernetes/
│   └── terraform/
├── api-gateway/
├── monitoring/
└── docs/

Resources