Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx

Introduction

In this blog post, we will walk through the process of deploying a FastAPI application on an AWS EC2 instance with Nginx as a reverse proxy, while leveraging GitHub Actions for Continuous Integration and Continuous Deployment (C…


This content originally appeared on DEV Community and was authored by Goodluck Ekeoma Adiole

Introduction

In this blog post, we will walk through the process of deploying a FastAPI application on an AWS EC2 instance with Nginx as a reverse proxy, while leveraging GitHub Actions for Continuous Integration and Continuous Deployment (CI/CD). This will ensure that every change pushed to the main branch is automatically deployed to the server.

By the end of this tutorial, you will have a fully functional, continuously deployed FastAPI application running on AWS.

Project Overview

We will be working with a FastAPI Book API and following these key steps:

  1. Implement the missing GET /api/v1/books/{book_id} endpoint.
  2. Test the application locally.
  3. Dockerize the application.
  4. Deploy it on an AWS EC2 instance.
  5. Set up Nginx as a reverse proxy.
  6. Configure GitHub Actions to automate deployment.

Step 1: Implement the Missing Endpoint

The application already provides endpoints for creating, updating, and deleting books, but we need to add an endpoint to retrieve a book by its ID.

Modify api/routes/books.py by adding the missing endpoint:

from typing import OrderedDict
from typing import Dict

from fastapi import APIRouter, status, HTTPException
from fastapi.responses import JSONResponse

from api.db.schemas import Book, Genre, InMemoryDB

router = APIRouter()

db = InMemoryDB()
db.books = {
    1: Book(
        id=1,
        title="The Hobbit",
        author="J.R.R. Tolkien",
        publication_year=1937,
        genre=Genre.SCI_FI,
    ),
    2: Book(
        id=2,
        title="The Lord of the Rings",
        author="J.R.R. Tolkien",
        publication_year=1954,
        genre=Genre.FANTASY,
    ),
    3: Book(
        id=3,
        title="The Return of the King",
        author="J.R.R. Tolkien",
        publication_year=1955,
        genre=Genre.FANTASY,
    ),
}

@router.post("/", status_code=status.HTTP_201_CREATED)
async def create_book(book: Book):
    db.add_book(book)
    return JSONResponse(
        status_code=status.HTTP_201_CREATED, content=book.model_dump()
    )

@router.get("/", response_model=OrderedDict[int, Book], status_code=status.HTTP_200_OK)
async def get_books() -> OrderedDict[int, Book]:
    return db.get_books()

@router.put("/{book_id}", response_model=Book, status_code=status.HTTP_200_OK)
async def update_book(book_id: int, book: Book) -> Book:
    return JSONResponse(
        status_code=status.HTTP_200_OK,
        content=db.update_book(book_id, book).model_dump(),
    )

@router.delete("/{book_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_book(book_id: int) -> None:
    db.delete_book(book_id)
    return JSONResponse(status_code=status.HTTP_204_NO_CONTENT, content=None)

# Added the missing api endpoint
@router.get("/{book_id}", response_model=Book, status_code=status.HTTP_200_OK)
async def get_book(book_id: int):
    book=db.books.get(book_id)
    if not book:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Book not found")
    return book

This ensures that a book is retrieved by its ID or returns a 404 Not Found error if it doesn't exist.

Step 2: Test the Application Locally

Before deploying, test the API locally using pytest:

pytest

To run the FastAPI application locally:

uvicorn api.main:app --host 0.0.0.0 --port 8084 --reload

Test the new endpoint with:

curl -X 'GET' 'http://127.0.0.1:8084/api/v1/books/1' -H 'accept: application/json'

Step 3: Dockerizing the Application

Create a Dockerfile in the root directory:

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8084"]

Build and run the Docker container:

docker build -t fastapi-app .
docker run -d -p 8084:8084 --name fastapi-container fastapi-app

Step 4: Deploy to AWS EC2

1. Launch an EC2 Instance

  • Choose Ubuntu 22.04.
  • Configure security groups to allow SSH (22), HTTP (80), and Custom TCP (8084).

2. SSH into the Instance

ssh -i your-key.pem ubuntu@your-ec2-public-ip

3. Install Docker and Git

sudo apt update && sudo apt install -y docker.io git

4. Clone the Repository and Run the Application

git clone https://github.com/yourusername/fastapi-book-project.git
cd fastapi-book-project
docker build -t fastapi-app .
docker run -d -p 8084:8084 --name fastapi-container fastapi-app

Test the application from your browser: http://your-ec2-public-ip:8084/api/v1/books/1

Step 5: Set Up Nginx as a Reverse Proxy

Install Nginx:

sudo apt install -y nginx

Modify the Nginx configuration file /etc/nginx/sites-available/default:

server {
    listen 80;
    server_name your-ec2-public-ip;

    location / {
        proxy_pass http://127.0.0.1:8084/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Restart Nginx:

sudo systemctl restart nginx

Now, your FastAPI application is accessible at http://your-ec2-public-ip/.

Step 6: Automate Deployment with GitHub Actions

Create .github/workflows/deploy.yml:

name: Deploy FastAPI to EC2

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Deploy to EC2
        uses: appleboy/ssh-action@v0.1.6
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ubuntu
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            cd ~/fastapi-book-project
            git pull origin main
            docker build -t fastapi-app .
            docker stop fastapi-container || true
            docker rm fastapi-container || true
            docker run -d -p 8084:8084 --name fastapi-container fastapi-app
            sudo systemctl restart nginx

Set Up GitHub Secrets

In your GitHub repository:

  • Navigate to Settings > Secrets > Actions.
  • Add EC2_HOST (EC2 public IP) and EC2_SSH_KEY (your private key).

Trigger Deployment

Run:

git add .
git commit -m "Test auto-deploy"
git push origin main

On a successful push to main, GitHub Actions will automatically deploy the app!

Challenges and Resolutions

1. Nginx Not Proxying Requests

Check Nginx logs:

sudo journalctl -u nginx --no-pager | tail -n 20

2. Docker Container Fails to Start

Verify logs:

docker logs fastapi-container

3. GitHub Actions SSH Key Issues

Ensure EC2_SSH_KEY secret is correctly set in GitHub.

Further Enhancements

  • Use AWS ECS instead of EC2 for better scalability.
  • Set up HTTPS with Let's Encrypt.
  • Store secrets securely using AWS Secrets Manager.

With this setup, you have a robust CI/CD pipeline that ensures seamless deployment of your FastAPI application. 🚀


This content originally appeared on DEV Community and was authored by Goodluck Ekeoma Adiole


Print Share Comment Cite Upload Translate Updates
APA

Goodluck Ekeoma Adiole | Sciencx (2025-02-15T23:48:32+00:00) Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx. Retrieved from https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/

MLA
" » Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx." Goodluck Ekeoma Adiole | Sciencx - Saturday February 15, 2025, https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/
HARVARD
Goodluck Ekeoma Adiole | Sciencx Saturday February 15, 2025 » Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx., viewed ,<https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/>
VANCOUVER
Goodluck Ekeoma Adiole | Sciencx - » Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/
CHICAGO
" » Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx." Goodluck Ekeoma Adiole | Sciencx - Accessed . https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/
IEEE
" » Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx." Goodluck Ekeoma Adiole | Sciencx [Online]. Available: https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/. [Accessed: ]
rf:citation
» Deploying a FastAPI Application on AWS EC2 with CI/CD Using GitHub Actions and Nginx | Goodluck Ekeoma Adiole | Sciencx | https://www.scien.cx/2025/02/15/deploying-a-fastapi-application-on-aws-ec2-with-ci-cd-using-github-actions-and-nginx/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.