Complete CI/CD Journey: From Code Commit to Live on AWS EC2

As a backend developer, I always believed that writing code is only half the job. The real challenge begins when you need to deploy, automate, scale, and maintain it reliably.
In this blog, I’ll walk you through my entire CI/CD journey, where I built a production-ready pipeline using:
GitHub Actions for CI/CD
Docker for containerization
AWS EC2 for hosting
Nginx as a reverse proxy
Free domain + HTTP
This setup is what I now confidently use for real production systems.
Problem Statement
Manually deploying applications caused multiple issues:
SSH into server every time
Build errors on server
Inconsistent environments
Downtime during deployments
Goal:
Push code → pipeline runs → app builds → deploys automatically → live with zero downtime
High-Level Architecture

AWS EC2 Setup (Foundation)
🔹 EC2 Instance
OS: Amazon Linux 2
Instance: t2.micro (free tier)
Security Group:

🔹 Connect to EC2
ssh -i shopx_rsa_key.pem ec2-user@3.81.27.12x
this will show something like this :

🔹 Install Essentials
sudo yum update -y
sudo yum install docker git -y
sudo service docker start
sudo usermod -aG docker ec2-user
Dockerizing the Spring Boot Application
🔹 Dockerfile

FROM eclipse-temurin:17-jdk
WORKDIR /app
COPY target/app.jar app.jar
EXPOSE 9000
ENTRYPOINT ["java", "-jar", "app.jar"]
Create Free Domain with DuckDns
Sign in to → https://www.duckdns.org/

select desired domain and add your Ec2 Public ipv4
hit this curl on shell before that add token from your account as shown in img.
curl "https://www.duckdns.org/update?domains=yourdomain&token=YOUR_TOKEN&ip="

this will return OK
now you are done!
Nginx Reverse Proxy Setup
A reverse proxy is a server that sits in front of backend servers and forwards client requests to them, handling things like routing, security, and load balancing.
🔹 Install Nginx
sudo yum install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
🔹create Nginx Config
sudo nano /etc/nginx/sites-available/shopx
🔹 Nginx Config
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:9000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
GitHub Actions – CI/CD Pipeline
🔹 Workflow File
.github/workflows/deploy.yml
name: CI-CD Pipeline
on:
push:
branches: [ "master" ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Build JAR
run: mvn clean package -DskipTests
- name: Build Docker Image
run: docker build -t sameers377/shopx_backend:latest .
- name: Login to DockerHub
run: echo ${{ secrets.DOCKERHUB_TOKEN }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin
- name: Push Docker Image
run: docker push sameers377/shopx_backend:latest
- name: Deploy to EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_KEY }}
script: |
./deploy.sh
8️⃣ Domain & HTTPS Setup
🔹 Domain Mapping
Domain → EC2 Public IP
DNS A-record
🔹 SSL (Let’s Encrypt)
sudo yum install certbot python3-certbot-nginx -y
sudo certbot --nginx
Now traffic is:
http://shopx-ecommerce.duckdns.org → Nginx → Spring Boot
What I Learned
CI/CD is a developer responsibility
Docker + GitHub Actions = powerful combo
Nginx is underrated but critical
Deployment confidence boosts development speed
Note on using AI
AI didn’t write my journey - it mentored me in refining my rough work into clarity.



