How I Deployed an App to AWS Using CI/CD + Terraform

Kaustav DeyKaustav Dey
3 min read

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 deployed a Dockerized application on AWS using Terraform and GitHub Actions. This project helped me apply core DevOps practices and build a production-ready pipeline.


Overview of the Stack

  • Terraform for infrastructure provisioning

  • EC2 for hosting the app

  • Docker to containerize the application

  • GitHub Actions for CI/CD

  • SCP + SSH for deployment automation


Step 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

By writing reusable Terraform modules, I was able to spin up the environment with a single command.


Step 2: Dockerizing the Application

The app I deployed was a simple Node.js server. I created a Dockerfile to containerize it:

FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 4000
CMD ["node", "app.js"]

Containerization ensured the app would run identically across development and production.


Step 3: CI/CD Pipeline with GitHub Actions

Next, I automated the build and deployment process using GitHub Actions. On every push to main, the pipeline:

  • Checked out the latest code

  • Established SSH access to the EC2 instance

  • Transferred files using scp

  • Remotely built and ran the Docker container

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 and Restart 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
          '

Secrets like EC2_SSH_KEY and EC2_HOST were stored securely in GitHub.


Step 4: Live Demo

After deployment, I could access the app at:

http://<EC2_PUBLIC_IP>:4000

Everything was running in the cloud with CI/CD automatically pushing updates on every commit.


Key Takeaways

  • Terraform makes infrastructure reproducible and scalable

  • Docker simplifies app deployment

  • GitHub Actions is powerful for automating delivery

  • Clean .env and .env.example handling is crucial for secrets

  • Real projects accelerate learning far more than passive tutorials


What’s Next

I plan to add CloudWatch monitoring and explore serverless patterns. I’m also expanding my portfolio with projects like:

  • Static site hosting on S3 + CloudFront

  • Auto-scaling EC2 groups

  • Secrets management with AWS SSM


Code and Demo


Let’s Connect

If you’re a solo developer or early-stage startup looking to deploy to AWS with CI/CD and infrastructure automation, I can help.


0
Subscribe to my newsletter

Read articles from Kaustav Dey directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Kaustav Dey
Kaustav Dey