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