This repository documents my complete end-to-end implementation of the Spider DevOps Induction Task, covering local setup, Dockerization, Nginx reverse proxy, and CI/CD automation using Jenkins and GitHub Webhooks.
The project consists of:
- Backend: Rust (Actix-Web) + Diesel ORM + PostgreSQL
- Frontend: React
- Infrastructure: Docker, Docker Compose, Nginx
- CI/CD: Jenkins (Dockerized) + GitHub App + Docker Hub
- Containerize a full-stack application
- Use Docker Compose for multi-service orchestration
- Set up Nginx as a reverse proxy
- Implement CI/CD using Jenkins
- Secure secrets using Jenkins Credentials
- Trigger automated builds on every GitHub push
| Layer | Technology |
|---|---|
| Backend | Rust, Actix-Web |
| ORM | Diesel |
| Database | PostgreSQL |
| Frontend | React |
| Reverse Proxy | Nginx |
| Containerization | Docker, Docker Compose |
| CI/CD | Jenkins (Docker) |
| Registry | Docker Hub |
| Webhooks | GitHub App + ngrok |
git clone https://github.com/Smya-Gangwar/Spider-Devops-Induction.git
cd Spider-Devops-Induction
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Homebrew is a package manager for macOS/Linux that simplifies installing developer tools.
brew install postgresql
brew services start postgresql
Create database:
psql postgres
CREATE DATABASE rust_server;
\q
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.zshrc
Rust is a systems programming language known for performance and safety.
cd Backend
Install Diesel CLI (Postgres support)
cargo install diesel_cli --no-default-features --features postgres
Environment Variables Create .env
DATABASE_URL=postgres://postgres:postgres@db:5432/rust_server
Initialize Database
diesel setup
Run Backend
cargo run
Resolved dependency conflicts using:
rm Cargo.lock
cargo clean
rm -rf ~/.cargo/registry
rm -rf ~/.cargo/git
cargo update -p time --precise 0.3.17
cargo build
cargo run
Removed the following from Cargo.toml:
[patch.crates-io]
time = "=0.3.17"
cd Frontend
brew install node@18
brew link node@18 --force
rm -rf node_modules package-lock.json
npm install
npm audit fix
npm install react-scripts@5.1.3
npm install http-proxy-middleware
npm start
Files Created
Backend/Dockerfile
Frontend/Dockerfile
Frontend/.dockerignore
docker-compose.yml
Key Changes
- setupProxy.js
target: "http://backend:8080"
- Backend .env (Docker networking)
DATABASE_URL=postgres://postgres:postgres@db:5432/rust_server
- Run Containers
docker-compose down
docker-compose build --no-cache
docker-compose up
In Backend/src/main.rs:
.bind("0.0.0.0:8080")
This is mandatory for Docker container networking.
nginx/nginx.conf
nginx/Dockerfile
docker-compose down -v
docker-compose build
docker-compose up -d
Why Docker Jenkins?
- Portable
- Same environment everywhere
- Production-like
- Version controlled
cd Jenkins
docker-compose up -d
Get admin password:
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
Access Jenkins: http://localhost:8080
App Name: jenkins-ci-cd-spider
Homepage URL: http://localhost:8080
Install ngrok:
brew install ngrok
ngrok config add-authtoken <YOUR_TOKEN>
ngrok http 8080
GitHub does not allow localhost webhooks, so ngrok is required.
- GitHub App (Private Key + App ID)
- GitHub Webhook Secret
- Docker Hub Username
- Docker Hub Access Token All secrets are stored securely in Jenkins Credentials.
- docker desktop start
- Up Jenkins Container
cd Jenkins && docker-compose up -d
- Start ngrok tunnel
ngrok http 8080 --host-header=rewrite
Any push to GitHub triggers the CI/CD pipeline automatically.
- GitHub Push
- GitHub Webhook
- Jenkins Pipeline a. Checkout Code b. Build Docker Images c. Push Images to Docker Hub d. docker-compose pull e. docker-compose up -d
- Nginx + Backend + Frontend + PostgreSQL
- Application live on http://localhost/
This level extends the CI/CD pipeline by deploying the containerized application to a cloud-hosted AWS EC2 instance.
- Login to AWS Console
- Create a new EC2 instance with the following configuration: a. Instance Name: spider-devops-ec2 b. AMI: Ubuntu Server 24.04 LTS c. Instance Type: t3.small d. Storage: 25 GB (gp3) e. Public IPv4: Enabled f. Key Pair: 1. Name: spider-ec2-key-v2 2. Type: RSA 3. Format: .pem
| Port | Protocol | Purpose |
|---|---|---|
| 22 | TCP | SSH |
| 80 | TCP | HTTP |
| 443 | TCP | HTTPS |
| 8080 | TCP | Jenkins (only if Jenkins runs on EC2) |
Source: IPv4 – Anywhere
- Launch the Instance
ssh -i spider-ec2-key-v2.pem ubuntu@3.109.1.112
sudo apt update
sudo apt install -y docker.io docker-compose-plugin
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker ubuntu
sudo apt install -y docker-compose
newgrp docker
git clone https://github.com/Smya-Gangwar/Spider-Devops-Induction.git
cd Spider-Devops-Induction
- Updated docker-compose.yml to pull images from Docker Hub
- Updated Jenkinsfile to deploy via SSH to EC2
- Kind: SSH Username with private key
- Scope: Global
- ID: ec2-ssh-key
- Description: AWS EC2 SSH Key
- Username: ubuntu
- Private Key: contents of spider-ec2-key-v2.pem
Generate SSH key on EC2:
ssh-keygen -t ed25519 -C "ec2-spider-devops"
Add key to SSH agent:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
Verify GitHub access:
ssh -T git@github.com
Update repository remote:
git remote set-url origin git@github.com:Smya-Gangwar/Spider-Devops-Induction.git
- Title: EC2 SSH Key
- Key Type: Authentication Key
- Key: contents of ~/.ssh/id_ed25519.pub
- GitHub push triggers Jenkins pipeline
- Jenkins builds Docker images
- Images pushed to Docker Hub
- Jenkins SSHs into EC2
- EC2 pulls latest images
- Containers restarted using Docker Compose
- Application becomes live
http://3.109.1.112