๐Ÿš€ Building a CI/CD Pipeline with GitHub Actions, Docker, and AWS EC2

Mahesh DiwanMahesh Diwan
3 min read

๐Ÿ‘‹ Introduction

In this blog, Iโ€™ll walk you through how I built a complete CI/CD pipeline to deploy a Flask application using GitHub Actions, Docker, and AWS EC2.

This hands-on project gave me a deeper understanding of DevOps practices like automated builds, containerization, and remote deployment โ€” all using free-tier AWS resources.


๐Ÿงฐ Tech Stack Used

ToolPurpose
FlaskPython web app
DockerContainerization
Docker HubContainer Registry
GitHub ActionsCI/CD Pipeline
AWS EC2Hosting the App

๐Ÿ—๏ธ Step 1: Create a Simple Flask App

I started with a minimal Flask app.

app.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return "Hello from Flask CI/CD on AWS!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

requirements.txt

flask

Test locally:

python3 app.py

Visit: http://localhost:5000


๐Ÿณ Step 2: Dockerize the App

Dockerfile

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

Build and run locally:

docker build -t flask-cicd .
docker run -p 5000:5000 flask-cicd

๐Ÿ“ค Step 3: Push Code to GitHub

I initialized a Git repo and pushed the code:

git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/mahesh-diwan/flask-cicd.git
git push -u origin master

๐Ÿ”— View Repo on GitHub


โ˜๏ธ Step 4: Push Docker Image to Docker Hub

docker tag flask-cicd maheshdiwan/flask-cicd:latest
docker push maheshdiwan/flask-cicd:latest

๐Ÿ”— Docker Hub Image


๐Ÿ” Step 5: GitHub Actions CI/CD Workflow

This GitHub Actions workflow automates:

  • Docker build on every push

  • Docker push to Docker Hub

  • SSH into EC2 and run the container

.github/workflows/deploy.yml

name: Build and Deploy

on:
  push:
    branches: [master]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and Push Docker image
        run: |
          docker build -t ${{ secrets.DOCKER_USERNAME }}/flask-cicd:latest .
          docker push ${{ secrets.DOCKER_USERNAME }}/flask-cicd:latest

      - name: Deploy to EC2 via SSH
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ubuntu
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            docker pull ${{ secrets.DOCKER_USERNAME }}/flask-cicd:latest
            docker stop flask-cicd || true
            docker rm flask-cicd || true
            docker run -d --name flask-cicd -p 5000:5000 ${{ secrets.DOCKER_USERNAME }}/flask-cicd:latest

โœ… Secrets are configured in the GitHub repo:

  • DOCKER_USERNAME

  • DOCKER_PASSWORD

  • EC2_HOST

  • EC2_SSH_KEY


๐Ÿ–ฅ๏ธ Step 6: Set Up EC2 on AWS

I launched a t2.micro Ubuntu EC2 instance, then:

  • Installed Docker:
sudo apt update
sudo apt install docker.io -y
  • Opened ports 22 and 5000 in the security group

  • Added my private SSH key to GitHub Secrets

  • Pushed to GitHub to trigger deployment


๐Ÿ“ˆ Final Architecture

GitHub โ†’ GitHub Actions โ†’ Docker Hub
                        โ†˜ SSH
                          AWS EC2 โ†’ Docker โ†’ Flask App (port 5000)

๐Ÿง  Key Takeaways

  • CI/CD automation reduces manual deployment work

  • Docker + GitHub Actions is an efficient pipeline combo

  • AWS EC2 gives full control over deployments

  • Real-world projects teach more than theory ever could!


๐Ÿ“Œ Final Notes

To save AWS credits, my EC2 instance is currently turned off.
You can still clone the project and run locally:

docker build -t flask-cicd .
docker run -p 5000:5000 flask-cicd

0
Subscribe to my newsletter

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

Written by

Mahesh Diwan
Mahesh Diwan