Python 2 min read

FastAPI Tutorial Part 16: Docker and Deployment

Deploy FastAPI applications to production. Learn Docker containerization, Docker Compose, cloud deployment, and production best practices.

MR

Moshiour Rahman

Advertisement

Dockerfile

Basic Dockerfile

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY ./app ./app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Production Dockerfile

FROM python:3.11-slim as builder

WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM python:3.11-slim

WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

COPY ./app ./app

RUN adduser --disabled-password --gecos "" appuser
USER appuser

EXPOSE 8000
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000"]

Docker Compose

# docker-compose.yml
version: "3.8"

services:
  api:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/app
      - SECRET_KEY=${SECRET_KEY}
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=app
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:alpine

  celery:
    build: .
    command: celery -A app.celery_app worker --loglevel=info
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/app
    depends_on:
      - redis
      - db

volumes:
  postgres_data:

Running

# Build and run
docker-compose up --build

# Run in background
docker-compose up -d

# View logs
docker-compose logs -f api

# Stop
docker-compose down

Environment Configuration

# app/config.py
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    database_url: str
    secret_key: str
    debug: bool = False
    allowed_hosts: list = ["*"]

    class Config:
        env_file = ".env"

settings = Settings()

Production Checklist

ItemAction
HTTPSUse reverse proxy (nginx)
SecretsEnvironment variables
LoggingStructured JSON logs
Health check/health endpoint
DatabaseConnection pooling
WorkersMultiple Gunicorn workers

Health Check Endpoint

@app.get("/health")
async def health_check():
    return {
        "status": "healthy",
        "database": await check_db_connection(),
        "redis": await check_redis_connection()
    }

Nginx Configuration

upstream api {
    server api:8000;
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://api;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Summary

ComponentPurpose
DockerfileContainer definition
docker-composeMulti-service orchestration
GunicornProduction WSGI server
NginxReverse proxy, SSL

Next Steps

In Part 17, we’ll explore Performance and Caching - optimizing your FastAPI application.

Series Navigation:

  • Part 1-15: Previous parts
  • Part 16: Docker & Deployment (You are here)
  • Part 17: Performance & Caching

Advertisement

MR

Moshiour Rahman

Software Architect & AI Engineer

Share:
MR

Moshiour Rahman

Software Architect & AI Engineer

Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.

Related Articles

Comments

Comments are powered by GitHub Discussions.

Configure Giscus at giscus.app to enable comments.