Last modified: Dec 01, 2025 By Alexander Williams
Deploy FastAPI with Docker for Production
FastAPI is a top Python framework. It is fast and modern. Docker is a container platform. It packages apps with all dependencies.
Together, they create a powerful deployment solution. This guide shows you how to deploy FastAPI with Docker.
We will cover everything from a basic setup to production-ready configurations.
Why Docker for FastAPI?
Docker solves the "it works on my machine" problem. It creates a consistent environment. This environment runs anywhere.
Your app runs the same on a laptop or a cloud server. Docker containers are lightweight and portable. They are perfect for microservices.
FastAPI apps often rely on specific Python versions and libraries. Docker ensures these are always present.
Prerequisites
You need a few things installed. First, have Python 3.7 or higher. You also need Docker Desktop or Docker Engine.
Basic knowledge of FastAPI and command line is helpful. If you are new, check our FastAPI Tutorial: Build Your First Python REST API.
Ensure you can install packages with pip. For setup help, see How to Install FastAPI in Python.
Creating a Simple FastAPI Application
Let's start with a basic app. Create a new directory for your project. Inside, make a file named main.py.
This file will contain our application code. We will create a simple API with one endpoint.
# main.py
from fastapi import FastAPI
# Create the FastAPI application instance
app = FastAPI(title="My Dockerized API")
# Define a simple root endpoint
@app.get("/")
def read_root():
return {"message": "Hello from Docker!"}
# Define a health check endpoint
@app.get("/health")
def health_check():
return {"status": "healthy"}
Next, create a requirements file. This lists our Python dependencies. Name it requirements.txt.
# requirements.txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
You can test the app locally first. Install the packages and run it.
pip install -r requirements.txt
uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Writing the Dockerfile
The Dockerfile is a set of instructions. It tells Docker how to build your image. Create a file named Dockerfile.
We will start with a simple single-stage build. This is good for learning.
# Dockerfile
# Use an official Python runtime as the base image
FROM python:3.11-slim
# Set the working directory in the container
WORKDIR /app
# Copy the requirements file first (for better caching)
COPY requirements.txt .
# Install the Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Copy the rest of the application code
COPY . .
# Expose the port the app runs on
EXPOSE 8000
# Command to run the application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Let's break down each instruction. The FROM command sets the base image.
We use a slim Python image to keep size small. WORKDIR sets the container's working directory.
Copying requirements.txt first is a best practice. It leverages Docker's layer caching.
The RUN command installs dependencies. Then we copy the rest of the app code.
EXPOSE informs Docker the container listens on port 8000. Finally, CMD defines the startup command.
Building and Running the Docker Image
Now, build your Docker image. Open a terminal in your project directory. Run the build command.
docker build -t fastapi-docker-app .
The -t flag tags the image with a name. The dot (.) means the current directory is the build context.
After the build finishes, run a container from your image.
docker run -d -p 8000:8000 --name my-fastapi-app fastapi-docker-app
The -d flag runs the container in detached mode. -p 8000:8000 maps port 8000 on your host to the container.
--name gives the container a friendly name. Now, open your browser. Go to http://localhost:8000.
You should see the JSON response. Also test the health endpoint at /health.
Optimizing for Production: Multi-Stage Builds
The simple Dockerfile works. But it is not ideal for production. The final image can be large.
It includes build tools and source code. We can optimize with a multi-stage build.
This uses one stage to build and another to run. The final image is much smaller.
# Dockerfile.prod
# Build stage
FROM python:3.11-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Final stage
FROM python:3.11-slim
WORKDIR /app
# Copy only the installed packages from the builder stage
COPY --from=builder /root/.local /root/.local
COPY . .
# Make sure scripts in .local are usable
ENV PATH=/root/.local/bin:$PATH
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
The first stage is named builder. It installs dependencies with --user.
The second stage starts fresh. It copies only the installed packages from the builder.
This removes build tools and cache. The final image is lean and secure.
Using Environment Variables
Hardcoding settings is bad practice. Use environment variables for configuration.
This lets you change settings without rebuilding the image. FastAPI can read these variables.
Update your main.py to use environment variables.
# main.py updated for environment variables
import os
from fastapi import FastAPI
app = FastAPI(title=os.getenv("APP_TITLE", "My Dockerized API"))
@app.get("/")
def read_root():
app_version = os.getenv("APP_VERSION", "1.0.0")
return {"message": "Hello from Docker!", "version": app_version}
Now, pass environment variables when running the container. Use the -e flag.
docker run -d -p 8000:8000 \
-e APP_TITLE="Production API" \
-e APP_VERSION="2.5.0" \
--name prod-app fastapi-docker-app
Adding a .dockerignore File
Don't copy unnecessary files into the image. This increases build time and size.
Create a .dockerignore file. It works like .gitignore.
# .dockerignore
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.venv/
.env
.git
.gitignore
README.md
Dockerfile
.dockerignore
tests/
*.log
.coverage
.idea/
.vscode/
This ignores cache files, virtual environments, and secrets. It also ignores development files.
Connecting to a Database
Most production apps need a database. You can link a database container.
Use Docker Compose to manage multiple services. For a detailed guide, see our FastAPI SQLAlchemy CRUD Guide.
Here is a simple docker-compose.yml example.
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Run it with docker-compose up -d. This starts both the app and the database.
Security Best Practices
Security is critical in production. Always run containers as a non-root user.
Update your Dockerfile to create and use a dedicated user.
# In your Dockerfile, before CMD
RUN addgroup --system appgroup && adduser --system --no-create-home --ingroup appgroup appuser
USER appuser
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
This reduces the attack surface. Also, keep your base images updated.
Scan your images for vulnerabilities regularly. Use trusted base images from official repositories.
Deploying to a Cloud Platform
Once your image is ready, you can deploy it. Popular platforms include AWS, Google Cloud, and Azure.
First, tag your image for a container registry. Then push it.
docker tag fastapi-docker-app username/repo:tag
docker push username/repo:tag
On your cloud platform, create a service. Point it to your image in the registry.
Configure environment variables, networking, and scaling. Each platform has specific guides.
Conclusion
Dockerizing your FastAPI app is straightforward. It ensures consistency and portability.
Start with a simple Dockerfile. Then move to multi-stage builds for production.
Use environment variables and a .dockerignore file. Always follow security best practices.
With Docker, you can deploy your FastAPI app anywhere. This includes cloud platforms and your own servers.
Your app will be reliable and scalable. For more advanced topics like authentication, explore our FastAPI JWT Authentication Python Tutorial.
Happy containerizing!