diff --git a/.env b/.env new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.env @@ -0,0 +1 @@ + diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml new file mode 100644 index 00000000..b7f64f60 --- /dev/null +++ b/.github/workflows/ci-cd.yml @@ -0,0 +1,30 @@ +name: CI-CD Pipeline + +on: + push: + branches: + - main + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: karthik0738 + password: Karthik@0738 + + - name: Build & Push Backend + run: | + docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/devops-assessment-backend ./backend + docker push ${{ secrets.DOCKERHUB_USERNAME }}/devops-assessment-backend + + - name: Build & Push Frontend + run: | + docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/devops-assessment-frontend ./frontend + docker push ${{ secrets.DOCKERHUB_USERNAME }}/devops-assessment-frontend diff --git a/DEVOPS.md b/DEVOPS.md new file mode 100644 index 00000000..d9687e82 --- /dev/null +++ b/DEVOPS.md @@ -0,0 +1,37 @@ +# DevOps Assessment – Full Stack Deployment + +## Project Overview +This project demonstrates containerization, orchestration, and CI/CD automation +for a full-stack application. + +**Backend:** Django (REST API) +**Frontend:** React (Vite + TypeScript) + +--- + +## Phase 1: Containerization + +### Backend +- Dockerized using Python slim image +- Dependencies installed via requirements.txt +- Exposed on port 8000 + +### Frontend +- Dockerized using Node Alpine image +- Built using npm +- Exposed on port 3000 + +### Orchestration +- docker-compose used to run both services +- Services communicate via internal Docker network +- Ports mapped to localhost for browser access + +### Run Locally +```bash +docker compose up --build + +## Infrastructure as Code (Terraform) + +- Used Terraform to provision AWS EC2 +- Defined Security Groups, EC2, and User Data +- Automated Docker installation via user_data diff --git a/Terraform/main.tf b/Terraform/main.tf new file mode 100644 index 00000000..a70a5491 --- /dev/null +++ b/Terraform/main.tf @@ -0,0 +1,45 @@ +resource "aws_instance" "devops_ec2" { + ami = var.ami_id + instance_type = var.instance_type + key_name = var.key_name + subnet_id = aws_subnet.public_subnet.id + + vpc_security_group_ids = [ + aws_security_group.devops_sg.id + ] + + tags = { + Name = "devops-ec2" + } +} +resource "aws_security_group" "devops_sg" { + name = "devops-sg" + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 3000 + to_port = 3000 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 8000 + to_port = 8000 + 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"] + } +} diff --git a/Terraform/outputs.tf b/Terraform/outputs.tf new file mode 100644 index 00000000..80e9a221 --- /dev/null +++ b/Terraform/outputs.tf @@ -0,0 +1,3 @@ +output "ec2_public_ip" { + value = aws_instance.devops_ec2.public_ip +} diff --git a/Terraform/provider.tf b/Terraform/provider.tf new file mode 100644 index 00000000..e542c84f --- /dev/null +++ b/Terraform/provider.tf @@ -0,0 +1,3 @@ +provider "aws" { + region = "us-east-1" +} diff --git a/Terraform/user_data.sh b/Terraform/user_data.sh new file mode 100644 index 00000000..23b8f6e6 --- /dev/null +++ b/Terraform/user_data.sh @@ -0,0 +1,6 @@ +#!/bin/bash +apt update -y +apt install docker.io docker-compose git -y +systemctl start docker +systemctl enable docker +usermod -aG docker ubuntu diff --git a/Terraform/variables.tf b/Terraform/variables.tf new file mode 100644 index 00000000..b03175d1 --- /dev/null +++ b/Terraform/variables.tf @@ -0,0 +1,11 @@ +variable "key_name" { + description = "EC2 key pair name" +} + +variable "instance_type" { + default = "t2.micro" +} + +variable "ami" { + default = "ami-0f58b397bc5c1f2e8" # Ubuntu 22.04 (us-east-1) +} diff --git a/backend/dockerfile b/backend/dockerfile new file mode 100644 index 00000000..d28b1b02 --- /dev/null +++ b/backend/dockerfile @@ -0,0 +1,19 @@ +FROM python:3.11-slim AS builder +WORKDIR /app +RUN apt-get update && apt-get install -y \ + build-essential \ + && rm -rf /var/lib/apt/lists/* +COPY requirements.txt . +RUN pip install --upgrade pip \ + && pip install --prefix=/install -r requirements.txt + +FROM python:3.11-slim +RUN useradd -m django +WORKDIR /app +COPY --from=builder /install /usr/local +COPY . . +RUN chown -R django:django /app +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +EXPOSE 8000 +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 00000000..75451f50 --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,3 @@ +Django>=4.2 +djangorestframework + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..b4b3b010 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +version: "3.9" + +services: + backend: + build: ./backend + container_name: backend + command: python manage.py runserver 0.0.0.0:8000 + volumes: + - ./backend:/app + ports: + - "8000:8000" + env_file: + - ./backend/.env + depends_on: + - frontend + + frontend: + build: ./frontend + container_name: frontend + command: npm start + volumes: + - ./frontend:/app + ports: + - "3000:3000" + build: + context: ./backend + container_name: django-backend + ports: + - "8001:8000" + volumes: + - ./backend:/app + command: python manage.py runserver 0.0.0.0:8000 + + frontend: + build: + context: ./frontend + container_name: react-frontend + ports: + - "3001:80" diff --git a/frontend/dockerfile b/frontend/dockerfile new file mode 100644 index 00000000..850df3a0 --- /dev/null +++ b/frontend/dockerfile @@ -0,0 +1,14 @@ +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +FROM nginx:alpine +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /app/dist /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] + diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 00000000..feb788de --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,10 @@ +server { + listen 80; + + location / { + root /usr/share/nginx/html; + index index.html; + try_files $uri /index.html; + } +} + diff --git a/terraform b/terraform new file mode 100644 index 00000000..972f24ac --- /dev/null +++ b/terraform @@ -0,0 +1 @@ +delete this file