The FastAPI Deployment Cookbook: Recipe for deploying FastAPI app with Docker and DigitalOcean"
Tags: fastapi, deployment, digitalocean, fastapideployment
Published: 2024-07-01 15:17:43

## From Local to Live: My Journey Deploying FastAPI with Docker on DigitalOcean

Hey there, fellow developers! Today, I want to share my recent experience deploying a FastAPI application using Docker on a DigitalOcean droplet. It was quite a learning curve, but I've broken it down into manageable steps that I hope will help you avoid some of the pitfalls I encountered. Let's dive in!

## What You'll Need Before We Start

- A DigitalOcean account (I'm using a basic droplet with Docker pre-installed)
- Some familiarity with Docker and FastAPI (but don't worry if you're new, we'll go through this together!)
- SSH access to your droplet

## Step 1: Crafting Your FastAPI App

First things first, let's create a simple FastAPI app. Here's the bare-bones version I started with:

**`main.py`**
```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"message": "Hello from FastAPI"}
```

Pretty straightforward, right? This just returns a JSON response when you hit the root endpoint.

## Step 2: Don't Forget Your Dependencies!

I learned this the hard way: always keep your `requirements.txt` updated. Here's what mine looks like:

**`requirements.txt`**
```plaintext
fastapi
uvicorn
```

Pro tip: Use `pip freeze > requirements.txt` to automatically generate this file from your current environment.

## Step 3: Dockerizing Your App

Now, let's containerize our app. Here's the Dockerfile I ended up with after some tweaking:

**`Dockerfile`**
```Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir -r requirements.txt
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]  #or second command will work only when your main.py file contains your initial fastapi setup
# CMD ["fastpi", "run", "--host", "0.0.0.0", "--port", "8000"]  
```
## Step 4: Building and Running Your Docker Container

Here's where the magic happens. SSH into your DigitalOcean droplet:

```sh
ssh user@your_droplet_ip
```
Note: You can build your docker image locally then push it on dockerhub and after that you can pull your app-image on your production server directly. But for now we are building our docker image on production sever
Once logged in, run these commands:

```sh
docker build -t fastapi-app .
docker run -d --name fastapi-app -p 8000:8000 fastapi-app
```

Quick tip: Add `--restart unless-stopped` to the `docker run` command to make your container restart automatically if it crashes or if your droplet reboots.

## Step 5: Verifying Your Deployment

After deployment, you can check the status of your running FastAPI app:

```sh
docker ps
```

To view the logs of your FastAPI app:

```sh
docker logs fastapi-app
```
To view stats of docker container usage(memory, cpu usage) of each running container

```sh
docker stats
```

## Step 6: Accessing Your Live Website

Your FastAPI app should now be accessible at `http://your_droplet_ip:8000`. Open this URL in your browser to see your live website!

**Important Note**: If your main file is named `main.py` and contains the FastAPI app instance named `app`, you can use the `fastapi run` command instead of the custom uvicorn setup. However, when using Docker, we typically stick with the uvicorn command for more control over the host and port settings.

## Step 7: Setting Up Nginx as a Reverse Proxy (Optional)

Setting up Nginx as a reverse proxy can improve performance and security. Here's how to do it:

1. Install Nginx:
   ```sh
   sudo apt update
   sudo apt install nginx
   ```

2. Create a new config file:
   ```sh
   sudo nano /etc/nginx/sites-available/fastapi
   ```

3. Add this configuration:
   ```nginx
   server {
       listen 80;
       server_name your_domain_or_ip;

       location / {
           proxy_pass http://localhost:8000;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
       }
   }
   ```

4. Enable the config and restart Nginx:
   ```sh
   sudo ln -s /etc/nginx/sites-available/fastapi /etc/nginx/sites-enabled/
   sudo systemctl restart nginx
   ```

If you set up Nginx, your app will be accessible at `http://your_droplet_ip` (without the port number).

## Bonus Tips I Wish I'd Known Earlier

1. **HTTPS is a must**: I highly recommend setting up HTTPS using Let's Encrypt. It's free and easier than you might think!

2. **Monitoring is key**: I use Prometheus and Grafana to keep an eye on my app's performance. It's saved me more than once!

3. **Automate your deployments**: Look into CI/CD pipelines. I use GitHub Actions, and it's been a game-changer for my workflow.

4. **Keep your images lean**: Use multi-stage builds to keep your Docker images as small as possible. It'll save you time and resources in the long run.

5. **Environment variables are your friends**: Don't hardcode sensitive information. Use environment variables or Docker secrets instead.

## Wrapping Up

Deploying FastAPI with Docker on DigitalOcean has been an exciting journey for me. It's opened up a whole new world of possibilities for my web development projects. I hope this guide helps you on your own deployment adventures!

Have you tried deploying FastAPI or any other Python web framework? I'd love to hear about your experiences in the comments. And if you found this guide helpful, don't forget to share it with your fellow devs!

Happy coding, and may your deployments always be smooth! 🚀