HNG DevOps Stage - 2

HNG DevOps Stage - 2

Deploying a FastAPI Application with CI/CD Pipeline

Introduction

As part of my HNG DevOps Internship, I was tasked with deploying a FastAPI application with a Continuous Integration (CI) and Continuous Deployment (CD) pipeline while ensuring the application is served using Nginx as a reverse proxy. This blog post will guide you step by step on how to complete this project.

Project Overview

In this task, we:

  1. Implement a missing API endpoint.

  2. Set up a CI pipeline to run tests using pytest.

  3. Configure a CD pipeline to deploy on merging into main.

  4. Dockerize the FastAPI application.

  5. Serve the application using Nginx.


Step 1: Fork the Template Repository

  1. Navigate to the given template repository on GitHub.

  2. Click on Fork to create a copy under your GitHub account.

  3. Clone your forked repository to your local machine:

     git clone https://github.com/your-username/fastapi-project.git
     cd fastapi-project
    

NOTE: THIS REPO IS NO LONGER UP.

Step 2: Implement the Missing Endpoint

We need to add an endpoint to retrieve a book by its ID.

Modify routes.py

  1. Open the routes.py file.

  2. Add the following function:

     from fastapi import FastAPI, HTTPException
     from models import books  # Assuming books is a predefined list or database object
    
     app = FastAPI()
    
     @app.get("/api/v1/books/{book_id}")
     async def get_book(book_id: int):
         book = next((book for book in books if book["id"] == book_id), None)
         if not book:
             raise HTTPException(status_code=404, detail="Book not found")
         return book
    
  3. Save the file and test it locally using uvicorn:

     uvicorn main:app --reload
    
  4. Open http://127.0.0.1:8000/docs to test the new endpoint.


Step 3: Set Up the CI Pipeline

A CI pipeline will run tests automatically.

Create .github/workflows/ci.yml

  1. Create a .github/workflows/ci.yml file with:

     name: CI
    
     on:
       pull_request:
         branches:
           - main
    
     jobs:
       test:
         runs-on: ubuntu-latest
         steps:
           - name: Checkout repository
             uses: actions/checkout@v3
           - name: Set up Python
             uses: actions/setup-python@v3
             with:
               python-version: "3.9"
           - name: Install dependencies
             run: |
               pip install -r requirements.txt
           - name: Run tests
             run: pytest
    
  2. Commit and push this file.

  3. Open a Pull Request and verify the test job runs successfully.


Step 4: Set Up the Deployment Pipeline

Create .github/workflows/deploy.yml

  1. Add a new file .github/workflows/deploy.yml:

     name: Deploy
    
     on:
       push:
         branches:
           - main
    
     jobs:
       deploy:
         runs-on: ubuntu-latest
         steps:
           - name: Checkout repository
             uses: actions/checkout@v3
           - name: Build and Push Docker Image
             run: |
               docker build -t my-fastapi-app .
               docker run -d -p 8000:8000 my-fastapi-app
    
  2. Push changes and merge a PR to test deployment.


Step 5: Dockerize the FastAPI App

Create Dockerfile

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
  1. Build and test locally:

     docker build -t fastapi-app .
     docker run -p 8000:8000 fastapi-app
    

Step 6: Set Up Nginx as a Reverse Proxy

Modify nginx.conf

  1. Create nginx.conf:

     server {
         listen 80;
         server_name localhost;
    
         location / {
             proxy_pass http://127.0.0.1:8000;
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
         }
     }
    
  2. Run Nginx with Docker:

     docker run --name nginx -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro -p 80:80 nginx
    

Step 7: Deploy the Application

  1. Push the Docker image to a registry (e.g., Docker Hub, AWS ECR, GitHub Container Registry).

     docker tag fastapi-app your-username/fastapi-app:latest
     docker push your-username/fastapi-app:latest
    
  2. Deploy to a cloud provider or a self-hosted server with Docker and Nginx configured.


Conclusion

This project strengthened my CI/CD automation, Dockerization, and Nginx deployment skills.

I successfully:

  1. Implemented a missing API endpoint

  2. Set up a deployment pipeline.

  3. Configured Nginx as a reverse proxy.

With each project I complete at HNG I learn a lot and I look forward to the next ones

#DevOps #FastAPI #Docker #GitHubActions #CI/CD #Nginx #CloudComputing