As a DevOps and cloud enthusiast, I wanted to go beyond theoretical knowledge and create something real. In this post, I’ll walk through how I provisioned infrastructure on AWS using Terraform and deployed a Dockerized app using GitHub Actions CI/CD. This project helped me apply core DevOps practices and build a production-ready pipeline from scratch.
🛠️ Stack Overview
- Terraform for infrastructure provisioning
- EC2 for hosting the app
- Docker to containerize the application
- GitHub Actions for CI/CD
- SCP + SSH for deployment automation
1️⃣ Infrastructure as Code with Terraform
I started by defining all infrastructure in Terraform to make deployments consistent and version-controlled. The configuration included:
- An EC2 instance with a public IP
- A security group allowing SSH (22), HTTP (80), and app port (4000)
- Optional Elastic Load Balancer for scalability
With reusable modules, I was able to spin up the entire environment with:
terraform init
terraform apply
2️⃣ Dockerizing the App
I deployed a simple Node.js app and containerized it using the following Dockerfile
:
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 4000
CMD ["node", "app.js"]
Containerization ensured consistent behavior across dev and prod.
3️⃣ CI/CD with GitHub Actions
To automate deployment, I set up a GitHub Actions pipeline triggered on every push to main
. It:
- SSHs into the EC2 instance
- Sends code using
scp
- Builds and runs a Docker container remotely
Here’s a simplified snippet of the deploy.yml
workflow:
name: Deploy to EC2
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up SSH
run: |
echo "${{ secrets.EC2_SSH_KEY }}" > key.pem
chmod 600 key.pem
- name: Deploy App
run: |
scp -i key.pem -r . ubuntu@${{ secrets.EC2_HOST }}:/home/ubuntu/app
ssh -i key.pem ubuntu@${{ secrets.EC2_HOST }} '
cd app &&
docker build -t myapp . &&
docker stop myapp || true &&
docker rm myapp || true &&
docker run -d -p 4000:4000 --name myapp myapp
All secrets like the SSH key and host IP are stored securely in GitHub.
✅ Results
Once deployed, the app was accessible at:
http://<EC2_PUBLIC_IP>:4000
Each push to GitHub automatically redeploys the latest code, saving time and ensuring consistency.
💡 Lessons Learned
- Terraform makes infra reproducible and scalable
- Docker simplifies app deployment
- GitHub Actions is powerful and integrates directly with your codebase
- Keeping sensitive values in
.env
and.env.example
is best practice
🔭 What's Next?
I’m planning to explore:
- Monitoring with CloudWatch
- Auto-scaling groups
- Using ECS or Fargate for container orchestration
🔗 Resources
- GitHub Repo: ci-cd-pipeline-aws
- Live Demo:
http://<your-ec2-ip>:4000
☎️ Let's Connect
If you're a solo dev or early-stage founder looking to deploy to AWS with CI/CD and infrastructure automation, I can help.
- Email: deykaustav357@gmail.com
- LinkedIn: https://www.linkedin.com/in/kaustav-dey-107593244
- Portfolio Website: Kaustav Dey DevOps & Cloud Specialist | AWS • Docker • Terraform • CI/CDm
Top comments (1)
If you're a solo dev or early-stage founder looking to deploy to AWS with CI/CD and infrastructure automation be sure to reach out