Flask API on AWS EC2


Deploying a Flask API to AWS EC2 Using Docker and GitHub Actions for CI/CD Pipeline
A complete walkthrough on building, containerizing, automating, and deploying a Flask REST API to AWS EC2 using Docker and GitHub Actions.
๐งญ Introduction
In this project, I created a simple Flask REST API, packaged it into a Docker container, and deployed it to an AWS EC2 instance via a CI/CD pipeline using GitHub Actions. This tutorial demonstrates how to:
Build a lightweight API using Flask
Containerize the application with Docker
Set up a GitHub Actions workflow for continuous integration and deployment
Deploy and manage the container on an EC2 instance automatically
๐ GitHub Repo: Flash_API-Docker-Project
โ๏ธ Phase 1: Building the Flask REST API
Weโll start with a minimal Flask app that provides basic CRUD functionality.
app.py:
from flask import Flask, jsonify, request
app = Flask(__name__)
data_store = []
@app.route("/", methods=["GET"])
def home():
return jsonify({"message": "Welcome to the Flask REST API!"})
@app.route("/items", methods=["GET"])
def get_items():
return jsonify(data_store)
@app.route("/items", methods=["POST"])
def add_item():
item = request.json
data_store.append(item)
return jsonify({"status": "Item added", "item": item}), 201
@app.route("/items/<int:index>", methods=["DELETE"])
def delete_item(index):
try:
removed = data_store.pop(index)
return jsonify({"status": "Item removed", "item": removed})
except IndexError:
return jsonify({"error": "Item not found"}), 404
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Screenshot: Sample response from the root endpoint
๐ณ Phase 2: Dockerizing the Flask App
Create a Dockerfile
to package the app.
Dockerfile:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
requirements.txt:
Flask==2.3.2
To build and test locally:
docker build -t flask-api .
docker run -d -p 5000:5000 flask-api
Screenshot: Docker container running locally
๐ Phase 3: Setting Up GitHub Actions for CI/CD
Create a workflow under .github/workflows/deploy.yml
.
Workflow Highlights:
Build Docker image
Push to Docker Hub
SSH into EC2 instance and deploy container
deploy.yml:
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/flask-api:latest
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
docker pull ${{ secrets.DOCKER_USERNAME }}/flask-api:latest
docker stop flask-api || true
docker rm flask-api || true
docker run -d --name flask-api -p 80:5000 ${{ secrets.DOCKER_USERNAME }}/flask-api:latest
Screenshot: GitHub Actions pipeline stages
โ๏ธ Phase 4: EC2 Deployment Output
Once the container is deployed, visiting the EC2 Public IP should show the root response.
Screenshot: API output from deployed EC2 instance
๐ GitHub Secrets to Configure
DOCKER_USERNAME
DOCKER_PASSWORD
EC2_HOST
EC2_USER
EC2_SSH_KEY
These are accessed securely in the GitHub Actions workflow.
๐ Summary
โ
Built a simple Flask REST API
โ
Containerized the app using Docker
โ
Automated deployment using GitHub Actions
โ
Deployed and verified the app on AWS EC2
๐ Repo: Flash_API-Docker-Project
๐ Final Thoughts
This project reinforced key DevOps principles including containerization, automation, and cloud deployment. It's a great starter for real-world CI/CD experience and can be extended with monitoring, HTTPS, and more advanced pipelines.
Feel free to fork the repo, try the steps, and drop your feedback or improvements!
Subscribe to my newsletter
Read articles from pradeep mahadevaiah directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
