FastAPI + Docker: Complete Steps for Containerized Deployment

Why Containerize?

When developing and deploying applications, we often encounter the issue of “it works on my machine” but “it doesn’t work on yours” – this is caused by environment inconsistencies. Docker containerization solves this problem by packaging your application and all its dependencies into an independent “box.” Whether running on any machine, opening this box will execute your application, as simple as opening a can.

FastAPI is a high-performance, easy-to-use Python API framework. When combined with Docker containerization, services developed with it become more convenient and consistent to deploy. Let’s implement this step by step.

I. Preparation: Write a Simple FastAPI Application

1. Install Python and Dependencies

First, ensure Python (version 3.7+) is installed on your computer. Create a project folder (e.g., fastapi-docker-demo) and create a main.py file inside it, which will be the entry point for your FastAPI application.

2. Write FastAPI Code

Add the following code to main.py:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}  # Returns Hello World when accessing the root path

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
    return {"item_id": item_id, "q": q}  # Example endpoint with parameters

This code creates a FastAPI application with two endpoints:
- The root path / returns the JSON data {"Hello": "World"}
- The parameterized path /items/{item_id} accepts an integer item_id and an optional string q

3. Generate Dependencies File

Open the command line in the project root directory and run:

pip install fastapi uvicorn  # Install FastAPI and Uvicorn (Uvicorn is FastAPI's recommended server)
pip freeze > requirements.txt  # Generate a dependencies file to record required packages

Your project directory structure should now look like this:

fastapi-docker-demo/
├── main.py
└── requirements.txt

II. Containerize the FastAPI Application with Docker

1. What is a Dockerfile?

A Dockerfile is a text file containing all the instructions to build a Docker image. We use it to tell Docker “how to package the FastAPI application into an image.”

2. Write the Dockerfile

Create a Dockerfile (without a file extension) in the project root directory with the following content:

# 1. Base image: Use a slimmed-down Python 3.9 image
FROM python:3.9-slim

# 2. Set the working directory (working path inside the container)
WORKDIR /app

# 3. Copy dependency files to the container (copying requirements.txt first leverages Docker caching for faster builds)
COPY requirements.txt .

# 4. Install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# 5. Copy all current directory files to the container's /app directory
COPY . .

# 6. Command to execute when the container starts: Launch the Uvicorn server
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Explanation of each line:
- FROM python:3.9-slim: Pulls a slimmed-down Python 3.9 image from Docker Hub (smaller size, suitable for production)
- WORKDIR /app: Creates and navigates to the /app directory inside the container; subsequent operations occur here
- COPY requirements.txt .: Copies the local requirements.txt to the container’s /app directory
- RUN pip install ...: Installs packages from the requirements file; --no-cache-dir avoids caching dependencies to reduce image size
- COPY . .: Copies all local files (excluding those in .dockerignore) to the container’s /app directory
- CMD ["uvicorn", ...]: Executes the Uvicorn command to start the FastAPI service when the container launches; --host 0.0.0.0 allows external access, and --port 8000 specifies the port

3. Ignore Unnecessary Files (Optional)

To prevent Docker from packaging files like __pycache__ or .git (which increase image size), create a .dockerignore file with:

__pycache__
*.pyc
*.pyo
*.pyd
.git
.gitignore

III. Build the Docker Image

1. Build Command

In the project root directory (ensure Docker is installed), run:

docker build -t my-fastapi-app .
  • -t my-fastapi-app: Tags the image with the name my-fastapi-app (customizable)
  • .: Indicates the Dockerfile is in the current directory

Docker will automatically build the image following the Dockerfile instructions. If successful, you’ll see Successfully built [image ID].

2. Verify Image Build

Check the local image list:

docker images

You should see the newly created my-fastapi-app image.

IV. Run the Docker Container

1. Start the Container

Execute the following command to start the container and map the container’s port 8000 to the host’s port 8000 (enabling browser access):

docker run -p 8000:8000 my-fastapi-app
  • -p 8000:8000: Port mapping (host_port:container_port)
  • my-fastapi-app: The name of the image to run

You’ll see log output like:

INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

This indicates the service is running and listening on the container’s port 8000 (configured via --host 0.0.0.0).

V. Test the Service

1. Access API Endpoints

Open a browser and visit http://localhost:8000; you should see the JSON response {"Hello": "World"}.

Alternatively, use the curl command:

curl http://localhost:8000

Output: {"Hello":"World"}

2. Access Auto-Generated API Documentation

FastAPI includes Swagger UI and ReDoc for easy debugging. Visit:

http://localhost:8000/docs

Here, you’ll find detailed descriptions of all endpoints. Click “Try it out” to test interface parameters directly.

VI. Common Issues and Solutions

1. Port Already in Use?

If you get an error like Bind to address 0.0.0.0:8000 failed, the port is occupied. Solutions:
- Change the port: Modify the CMD in Dockerfile to uvicorn main:app --host 0.0.0.0 --port 8001, rebuild the image, and use -p 8001:8001 when starting the container
- Stop the occupying process: On Windows, use netstat -ano | findstr 8000 to find the PID, then taskkill /PID [PID] /F; on Linux/Mac, use lsof -i :8000 to find the PID and kill [PID]

2. How to Rerun After Code Changes?

After modifying code, rebuild the image and restart the container:

# Stop the previous container (if not running in detached mode)
docker stop [container ID]
# Rebuild the image
docker build -t my-fastapi-app .
# Restart the container
docker run -p 8000:8000 my-fastapi-app

VII. Summary

By containerizing FastAPI with Docker, you can:
1. Ensure consistency across development, testing, and production environments, eliminating “it works on my machine” issues
2. Quickly migrate services by simply copying image files
3. Isolate application dependencies for lighter deployments

Future optimizations could include:
- Using Docker Compose to manage multiple services (e.g., FastAPI + database)
- Configuring Nginx for reverse proxy and HTTPS
- Deploying to cloud platforms (e.g., Alibaba Cloud, AWS, Google Cloud)

Now you’ve mastered the basic deployment process for FastAPI + Docker. Start containerizing your API services for one-click deployment!

Xiaoye