In today’s microservices architecture, containerization has become crucial to application deployment. This guide will walk you through containerizing a FastAPI application using Docker, from basic setup to production-ready deployment.
Table of Contents
Prerequisites
Before we begin, ensure you have the following installed:
- Python 3.8+
- Docker
- Docker Compose (optional, but recommended)
- FastAPI and Uvicorn
Project Setup
Let’s start with a basic FastAPI project structure:
my_fastapi_app/
├── app/
│ ├── init.py
│ ├── main.py
│ └── api/
│ └── init.py
├── Dockerfile
├── docker-compose.yml
└── requirements.txt
Create a simple FastAPI application in app/main.py
:
from fastapi import FastAPI
app = FastAPI(title="My FastAPI App")
@app.get("/")
async def root():
return {"message": "Hello, Docker!"}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
Dockerizing Your FastAPI Application
Create a Dockerfile
:
# Use official Python runtime as the base image
FROM python:3.9-slim
# Set working directory in the container
WORKDIR /app
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Install system dependencies
RUN apt-get update \
&& apt-get install -y --no-install-recommends gcc \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the project files into the container
COPY ./app ./app
# Command to run the application
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Your requirements.txt
should include:
fastapi>=0.68.0
uvicorn>=0.15.0
pydantic>=1.8.0
Development vs. Production Configurations
Create a docker-compose.yml
for development:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
volumes:
- ./app:/app/app
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
environment:
- ENVIRONMENT=development
- DEBUG=1
For production, create a docker-compose.prod.yml
:
version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- "8000:8000"
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
environment:
- ENVIRONMENT=production
- DEBUG=0
restart: unless-stopped
Best Practices and Optimization
1. Multi-stage Builds
For production, use multi-stage builds to reduce image size:
# Build stage
FROM python:3.9-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /app/wheels -r requirements.txt
# Final stage
FROM python:3.9-slim
WORKDIR /app
COPY --from=builder /app/wheels /wheels
COPY --from=builder /app/requirements.txt .
RUN pip install --no-cache /wheels/*
COPY ./app ./app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
2. Security Best Practices
- Run as a non-root user
- Use specific package versions
- Implement health checks
Add to your Dockerfile:
# Create non-root user
RUN adduser --system --group app
USER app
# Add health check
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
Scaling with Docker Compose
For horizontal scaling, update your docker-compose.prod.yml
:
version: '3.8'
services:
web:
build: .
deploy:
replicas: 4
resources:
limits:
cpus: '0.50'
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
Deployment Considerations
- Environment Variables
- Use
.env
files for development - Use secure secrets management in production
- Never commit sensitive data to version control
- Use
- Logging Configure logging in your FastAPI application:
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
Monitoring
- Implement Prometheus metrics
- Use container monitoring solutions
- Set up alerting for critical issues
Conclusion
Containerizing your FastAPI application with Docker provides numerous benefits:
- Consistent development environments
- Easy scaling and deployment
- Better resource utilization
- Simplified dependency management
Remember to:
- Always use production-grade ASGI servers like Uvicorn or Gunicorn
- Implement proper logging and monitoring
- Follow security best practices
- Optimize your Docker images for production
By following this guide, you’ll have a solid foundation for deploying FastAPI applications in containers, ready for production use.