# HNG DevOps Stage - 2

## 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:
    
    ```sh
    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`](http://routes.py)

1. Open the [`routes.py`](http://routes.py) file.
    
2. Add the following function:
    
    ```python
    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`:
    
    ```sh
    uvicorn main:app --reload
    ```
    
4. Open [`http://127.0.0.1:8000/docs`](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:
    
    ```yaml
    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`:
    
    ```yaml
    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`

```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:
    
    ```sh
    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`:
    
    ```nginx
    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:
    
    ```sh
    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).
    
    ```sh
    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
