DEV Community

Adetola Hannah
Adetola Hannah

Posted on

Deploying a FastAPI Application with CI/CD and Nginx

Introduction

In this blog post, we will walk through deploying a FastAPI application with a Continuous Integration (CI) and Continuous Deployment (CD) pipeline. The application will be served using Nginx as a reverse proxy.

Prerequisites

  • Basic knowledge of FastAPI and Python
  • A GitHub repository (fork the provided FastAPI template repository)
  • Docker installed on your machine
  • An Ubuntu server or cloud VM for deployment
  • Nginx installed on the server
  • GitHub Actions for CI/CD

Step 1: Clone the Repository and Create a Virtual Environment

# Clone the repository
git clone https://github.com/your-username/fastapi-book-project.git
cd fastapi-book-project

# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate  # On Windows use `venv\Scripts\activate`

# Install dependencies
pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Step 2: Implement the Missing Endpoint

Edit main.py and add the following code:

from fastapi import FastAPI, HTTPException
from typing import Dict

app = FastAPI()

books = {
    1: {"title": "Book One", "author": "Author One"},
    2: {"title": "Book Two", "author": "Author Two"}
}

@app.get("/api/v1/{book_id}")
def get_book(book_id: int) -> Dict:
    if book_id in books:
        return books[book_id]
    raise HTTPException(status_code=404, detail="Book not found")
Enter fullscreen mode Exit fullscreen mode

Step 3: Add Tests with Pytest

Create a test_main.py file in the root directory:

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_get_existing_book():
    response = client.get("/api/v1/1")
    assert response.status_code == 200
    assert response.json() == {"title": "Book One", "author": "Author One"}

def test_get_nonexistent_book():
    response = client.get("/api/v1/999")
    assert response.status_code == 404
    assert response.json() == {"detail": "Book not found"}
Enter fullscreen mode Exit fullscreen mode

Run the tests locally:

pytest
Enter fullscreen mode Exit fullscreen mode

Step 4: Set Up the CI Pipeline with GitHub Actions

Create .github/workflows/test.yml:

name: CI Pipeline

on:
  pull_request:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: "3.9"
      - name: Install dependencies
        run: |
          python -m venv venv
          source venv/bin/activate
          pip install -r requirements.txt
          pip install pytest
      - name: Run tests
        run: |
          source venv/bin/activate
          pytest
Enter fullscreen mode Exit fullscreen mode

Step 5: Create a Dockerfile

Create a Dockerfile:

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

Build and run the Docker container:

docker build -t fastapi-app .
docker run -p 8000:8000 fastapi-app
Enter fullscreen mode Exit fullscreen mode

Step 6: Configure Nginx as a Reverse Proxy

Create an Nginx config file /etc/nginx/sites-available/fastapi:


nginx
server {
    listen 80;
    server_name your_domain_or_IP;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_h
Enter fullscreen mode Exit fullscreen mode

Top comments (0)