ak-127 / sai-prj1
⭐ DevOps Project

Django CI/CD
Pipeline on AWS

A production-ready DevOps workflow — Dockerized Django app with Jenkins CI/CD, PostgreSQL, Nginx reverse proxy, and automated AWS EC2 deployment. Zero manual deployments.

🐳 Docker + Compose
🔧 Jenkins CI/CD
☁️ AWS EC2
🐍 Django 5.0.6
🗄️ PostgreSQL 15
🌐 Nginx Proxy
🔒 Security Best Practices
5
Pipeline Stages
3
Containers
0
Manual Deploys
Production Grade
Automated Workflow

CI/CD Pipeline Flow

Every git push to main triggers the full automated pipeline — from code checkout to live deployment on AWS EC2.

👨‍💻
Developer
git push main
Trigger
🐙
GitHub
Webhook fired
SCM
🔧
Jenkins
Build + Test
CI Server
🐳
Docker
Image Build
Container
☁️
AWS EC2
Live Deploy
Production
🌐
Live App
:80 Online
Deployed ✓
System Design

Infrastructure Architecture

Full-stack architecture running inside Docker containers on AWS EC2 — Nginx handles all incoming traffic, routing to the Django/Gunicorn app, backed by PostgreSQL.

AWS EC2 Docker Network 🌐 Client Browser/HTTP Port 80/443 HTTP 🌐 Nginx Reverse Proxy SSL · Static · Gzip :80, :443 :8000 🐍 Django App Gunicorn WSGI Blog · Auth · Admin :8000 psycopg2 🗄️ PostgreSQL v15 Database Users · Posts · Media tcp://db:5432 📂 Volumes static/ · media/ · postgres_data/ 🔧 Jenkins CI/CD Server Build · Test · Deploy SSH Deploy ● Animated data flows ● Nginx handles all ingress ● Containers share Docker network
Automation Engine

Jenkins Pipeline Stages

The Jenkinsfile defines 5 automated stages. Every push to main runs the full pipeline end-to-end — no human intervention required.

📥
Checkout
Pull latest code from GitHub main branch via webhook
🏗️
Docker Build
Build Django & Nginx images using Dockerfile
🧪
Run Tests
Execute Django unit tests inside the container
📦
Push Images
Update built Docker images to registry
🚀
Deploy
SSH to EC2, run docker-compose up -d
Zero Manual Deploys
Every push to main deploys automatically. No SSH, no manual steps.
🔄
Faster Releases
Code-to-production in minutes. Continuous delivery at every commit.
🛡️
Reduced Human Error
Automated pipeline ensures consistent, repeatable deployments every time.
📊
Build Visibility
Full build logs, stage-by-stage results, and failure notifications via Jenkins dashboard.
Jenkinsfile
● Declarative Pipeline
pipeline {
  agent any

  stages {
    stage('Checkout') {
      steps { checkout scm }
    }

    stage('Build Docker Images') {
      steps {
        sh 'docker-compose build'
      }
    }

    stage('Run Tests') {
      steps {
        sh 'docker-compose run --rm web python manage.py test'
      }
    }

    stage('Deploy to EC2') {
      steps {
        sh '''
          docker-compose down
          docker-compose up -d --build
        '''
      }
    }
  }

  post {
    success { echo '✅ Deployed successfully!' }
    failure { echo '❌ Build failed — check logs' }
  }
}
Containerization

Docker Services

Three services defined in docker-compose.yml — isolated, networked, and orchestrated with shared volumes and environment config.

docker-compose.yml — Services
🌐
nginx
reverse proxy
image: nginx:alpine
ports: "80:80", "443:443"
volumes: ./nginx.conf, static/, media/
depends_on: web
🐍
web
django app
build: . (Dockerfile)
command: gunicorn wsgi:application
ports: "8000:8000"
env_file: .env
depends_on: db
🗄️
db
postgresql
image: postgres:15-alpine
ports: "5432:5432"
volumes: postgres_data:/var/lib/postgresql
env_file: .env (DB credentials)
🔗 Shared Docker Network
nginx
web
db
Dockerfile
# Multi-stage Python build
FROM python:3.11-slim

WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# System dependencies
RUN apt-get update && apt-get install \
    libpq-dev gcc --no-install-recommends

# Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Collect static files
RUN python manage.py collectstatic --noinput

EXPOSE 8000
ENTRYPOINT ["./entrypoint.sh"]
nginx.conf
upstream django {
    server web:8000;
}

server {
    listen 80;

    location /static/ {
        alias /vol/web/static/;
    }

    location /media/ {
        alias /vol/web/media/;
    }

    location / {
        proxy_pass http://django;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
Cloud Infrastructure

AWS EC2 Setup

Ubuntu EC2 instance hosts the entire containerized stack. Security groups open only the required ports. Jenkins deploys via SSH using key-based authentication.

EC2 Ubuntu Instance
🌐
Nginx Container
nginx:alpine — :80, :443 → Reverse Proxy
🐍
Web (Django/Gunicorn)
python:3.11-slim — :8000 → Application Server
🗄️
PostgreSQL Database
postgres:15-alpine — :5432 → Persistent storage
Security Group — Open Ports
SSH :22
HTTP :80
HTTPS :443
DB :5432 (internal)
🖥️
EC2 Instance (Ubuntu)
Ubuntu Linux as the base OS. Docker and Docker Compose installed. Jenkins deploys to this instance via SSH. All containers run here as a single deployment unit.
🔑
SSH Key Auth
Jenkins uses SSH key-based authentication to connect to EC2. No passwords. Private key stored securely in Jenkins credential manager. EC2 public key in authorized_keys.
🔒
Security Groups
Minimal port exposure — only SSH (22), HTTP (80), and HTTPS (443) open to the world. Database port 5432 restricted to internal Docker network only.
💾
EBS Storage + Volumes
Docker named volumes persist data between container restarts — postgres_data for the DB, /vol/web/static and /vol/web/media for Django assets. EBS backs the instance.
Step-by-Step Guide

How to Deploy

Full deployment walkthrough — from cloning the repo to a live production app on AWS EC2 in 6 steps.

1
Clone & Configure
# Clone the repository
git clone https://github.com/ak-127/sai-prj1.git cd sai-prj1
# Copy environment template
cp .env.example .env
Clone the repo and copy the environment file. Edit .env with your DB credentials, Django SECRET_KEY, and ALLOWED_HOSTS.
2
Provision EC2 Instance
# On AWS Console:
Launch Ubuntu 22.04 EC2 (t2.micro+) Configure Security Group: - Port 22 (SSH) - Port 80 (HTTP) - Port 443 (HTTPS) Assign/note Elastic IP
Create an Ubuntu EC2 instance. Set up security group rules for SSH, HTTP, and HTTPS. Download your .pem key pair for SSH access.
3
Install Docker on EC2
# SSH into your EC2
ssh -i your-key.pem ubuntu@EC2_IP
# Run the install script
chmod +x install.sh ./install.sh
# Verify
docker --version docker compose version
SSH into the EC2 instance and run the included install.sh script which installs Docker, Docker Compose, and all required system dependencies.
4
Setup Jenkins Pipeline
# In Jenkins dashboard:
New Item → Pipeline Configure GitHub repo URL Add webhook in GitHub: Payload URL: http://JENKINS_URL/ Content type: application/json Event: Push
# Add EC2 SSH credentials
Manage Jenkins → Credentials Add: SSH Username with private key
Create a new Pipeline job in Jenkins. Configure the GitHub webhook so every push to main triggers the Jenkinsfile pipeline automatically.
5
Build & Launch
# Manual first deploy on EC2:
git clone https://github.com/ak-127/sai-prj1.git cd sai-prj1 cp .env.example .env nano .env # Fill in secrets docker compose up -d --build
# Run migrations
docker compose exec web \ python manage.py migrate
# Create superuser
docker compose exec web \ python manage.py createsuperuser
On first deploy, run docker compose up -d --build manually on EC2. After this, all subsequent deploys happen automatically via Jenkins on every git push.
6
Verify & Monitor
# Check container health
docker compose ps docker compose logs -f web
# Check Nginx is running
curl http://your-ec2-ip
# Access Django admin
http://your-ec2-ip/admin/
# Monitor logs
docker compose logs --tail=50 -f
Verify all containers are running with docker compose ps. Access the app at your EC2 IP on port 80. Admin panel at /admin/. Watch live logs with the logs command.
.env — Environment Configuration
⚠ Never commit this file
# Django Configuration
SECRET_KEY=your-super-secret-django-key-here
DEBUG=0
ALLOWED_HOSTS=your-ec2-ip,your-domain.com

# Database Configuration
DB_NAME=saikrupa_db
DB_USER=postgres_user
DB_PASSWORD=strong-password-here
DB_HOST=db
DB_PORT=5432

# Django static / media
STATIC_URL=/static/
MEDIA_URL=/media/
What Powers This

Full Tech Stack

Category
Technology
Role in Project
🐍 Backend
Django 5.0.6 + Gunicorn
Web framework + WSGI application server. Handles routing, auth, admin, blog logic.
🗄️ Database
PostgreSQL 15 + Psycopg2
Relational DB for all persistent data. ACID compliant with persistent Docker volume.
🌐 Proxy
Nginx (Alpine)
Reverse proxy, SSL termination, static file serving, Gzip compression.
🐳 Containers
Docker + Docker Compose
Containerizes all 3 services. Compose manages networking, volumes, dependencies.
🔧 CI/CD
Jenkins (Declarative Pipeline)
Automated build, test, and deploy pipeline. Triggered by GitHub webhooks on every push.
☁️ Cloud
AWS EC2 (Ubuntu)
Cloud compute instance hosting the full Docker stack. EBS for persistent block storage.
🔐 Auth
Django Auth + .env
Built-in Django authentication. Secrets managed via .env — not hardcoded, not committed.
📦 VCS
Git + GitHub
Version control + remote repo. GitHub webhooks trigger Jenkins pipeline on every commit.
Best Practices

Security Architecture

🔐
Secrets via .env
All sensitive config — DB passwords, SECRET_KEY, API keys — stored in .env file, excluded from git via .gitignore. Never hardcoded in source.
🔑
SSH Key Auth
EC2 access uses key-based SSH authentication only. Password auth disabled. Jenkins stores the private key in its encrypted credential store.
🛡️
Minimal Port Exposure
AWS Security Group exposes only ports 22, 80, 443. PostgreSQL port 5432 is internal-only — never accessible from outside the Docker network.
🌐
Nginx as Proxy
Nginx sits in front of Django — the app server is never directly exposed. Nginx handles SSL termination, headers, and rate limiting.
📦
Container Isolation
Each service runs in its own isolated container with separate filesystem. Breach of one container doesn't automatically compromise others.
🔒
Jenkins Credentials
SSH keys and API tokens stored in Jenkins Credential Manager — encrypted at rest. Never logged in build output or stored in plain text config.
What's Next

Future Improvements

☸️
Kubernetes (EKS) Migration
Move from Docker Compose to Kubernetes on AWS EKS for auto-scaling, self-healing, and rolling deployments.
In Progress
🏗️
Terraform IaC
Provision the entire AWS infrastructure — EC2, VPC, SGs, EBS — via Terraform for reproducible, version-controlled infrastructure.
Planned
📊
Prometheus + Grafana Monitoring
Add full observability stack — container metrics, Django app metrics, PostgreSQL performance dashboards in Grafana.
Planned
🔐
HTTPS with Let's Encrypt
Add free SSL certificates via Certbot + Nginx. Auto-renewal configured. Force HTTP → HTTPS redirects for production security.
In Progress
🔵
Blue-Green Deployment
Zero-downtime deployments using blue-green strategy. Switch traffic between environments with Nginx upstream config changes.
Future
🚨
Centralized Log Management
Ship all container logs to ELK Stack (Elasticsearch + Logstash + Kibana) for centralized log analysis and alerting.
Future