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 |
Featured Project: Complete Web Application
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
# 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]
}
}
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