Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: CI-CD Pipeline

on:
push:
branches:
- main

jobs:
docker-build-push:
runs-on: ubuntu-latest

steps:
# Step 1: Checkout code
- name: Checkout repository
uses: actions/checkout@v4

# Step 2: Login to Docker Hub
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# Step 3: Build Docker image
- name: Build Docker image
run: |
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/devops-assessment:latest .

# Step 4: Push Docker image
- name: Push Docker image
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/devops-assessment:latest
89 changes: 89 additions & 0 deletions Devops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Docker-Based DevOps Deployment (with Terraform & CI/CD)

## Overview
This document describes the **Docker-based deployment strategy** for a full-stack application, enhanced with **CI/CD automation using GitHub Actions** and **Infrastructure as Code (IaC) using Terraform**.

The focus of this setup includes:
- Containerization using Docker
- Service orchestration using Docker Compose
- Automated image build and push using GitHub Actions
- Cloud infrastructure provisioning using Terraform

---

## Application Stack

- **Backend:** Django (REST API)
- **Frontend:** React (Vite + TypeScript)
- **Containerization:** Docker
- **Orchestration:** Docker Compose
- **CI/CD:** GitHub Actions
- **Infrastructure as Code:** Terraform
- **Cloud Platform:** AWS

---

## Docker Containerization

### Backend (Django)
- Dockerized using a **Python slim base image**
- Dependencies installed using `requirements.txt`
- REST API exposed on **port 8000**
- Runs as a standalone Docker container

### Frontend (React – Vite + TypeScript)
- Dockerized using a **Node Alpine base image**
- Application built using **npm**
- Frontend exposed on **port 3000**
- Served through a Docker container

---

## Docker Compose Orchestration

- `docker-compose.yml` is used to manage multi-container deployment
- Backend and frontend run as **separate services**
- Services communicate via an **internal Docker network**
- Ports are mapped to the host system for browser access

### Port Mapping

| Service | Container Port | Host Port |
|--------|----------------|-----------|
| Backend | 8000 | 8000 |
| Frontend | 3000 | 3000 |

---

## Run Application Using Docker

### Prerequisites
- Docker
- Docker Compose

### Command
```bash
docker compose up --build
```
## Terraform (Infrastructure as Code)

Terraform is used alongside Docker to provision and manage cloud infrastructure required for deployment.

### Terraform Integration with Docker Workflow
- Terraform code is stored in `infra-terraform/`
- Infrastructure is defined using `.tf` files
- Enables automated provisioning of cloud resources (e.g., EC2, networking)
- Ensures Docker containers run on consistent and reproducible infrastructure

### Terraform Commands
```bash
terraform init
terraform validate
terraform plan
terraform apply
```

## GitHub Actions CI/CD

GitHub Actions automates Docker image build, push, and Terraform validation on every push to the `main` branch, ensuring consistent deployments and early infrastructure validation.

22 changes: 22 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Python cache
__pycache__/
*.pyc
*.pyo
*.pyd

# Virtual environments (VERY IMPORTANT)
venv/
.venv/
env/

# Git
.git/
.gitignore

# Frontend / build junk (safe even if not present)
node_modules/
dist/
build/

# Local DB
*.sqlite3
47 changes: 47 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -------- Builder stage --------
FROM python:3.12-slim AS builder

WORKDIR /app

# System dependencies
RUN apt-get update && apt-get install -y \
build-essential gcc libpq-dev \
&& rm -rf /var/lib/apt/lists/*

# Create virtual environment
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Install Python dependencies
RUN pip install --upgrade pip
RUN pip install django django-cors-headers psycopg2-binary

# Copy project source (venv is ignored via .dockerignore)
COPY . .

# -------- Runtime stage --------
FROM python:3.12-slim

WORKDIR /app

# Create non-root user
RUN useradd -m appuser

# Copy venv and app from builder
COPY --from=builder /opt/venv /opt/venv
COPY --from=builder /app /app

# Permissions
RUN chown -R appuser:appuser /app /opt/venv

USER appuser

# Environment variables
ENV PATH="/opt/venv/bin:$PATH"
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DJANGO_SETTINGS_MODULE=config.settings

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
32 changes: 16 additions & 16 deletions backend/config/asgi.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
"""
ASGI config for config project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')

application = get_asgi_application()
"""
ASGI config for config project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_asgi_application()
Loading