docker.recipes

Production FastAPI Stack

advanced

Production FastAPI with Nginx, Uvicorn, PostgreSQL, Redis, and Celery workers

Overview

FastAPI is a modern, high-performance web framework for building APIs with Python, designed around Python type hints and automatic API documentation generation. This production stack combines FastAPI with Uvicorn's ASGI server for async request handling, Nginx as a reverse proxy for load balancing and static file serving, PostgreSQL for reliable ACID-compliant data storage, and Redis powering both caching and Celery's distributed task queue system. The architecture creates a robust, scalable API platform capable of handling both synchronous web requests and asynchronous background processing. This stack addresses the common production challenges of API development: horizontal scaling through Uvicorn workers, request buffering and SSL termination via Nginx, data persistence with PostgreSQL's advanced features like JSONB support, and background job processing through Celery workers with Redis as the message broker. The inclusion of Flower provides real-time monitoring of Celery tasks, while Celery Beat enables scheduled job execution. This configuration is ideal for SaaS platforms, data processing APIs, and enterprise applications that require both immediate API responses and background task execution. The combination of FastAPI's automatic OpenAPI documentation, PostgreSQL's query optimization capabilities, and Celery's distributed processing makes this stack particularly valuable for teams building complex data-driven applications that need to scale beyond simple CRUD operations.

Key Features

  • FastAPI's automatic OpenAPI and JSON Schema generation with interactive documentation at /docs endpoint
  • Uvicorn ASGI server with configurable worker processes for handling concurrent async requests
  • Nginx reverse proxy with event-driven architecture for high-throughput request handling and static file serving
  • PostgreSQL JSONB support enabling hybrid relational-document data models within a single database
  • Redis Pub/Sub messaging for real-time communication between API and Celery workers
  • Celery distributed task queue with separate worker and beat scheduler containers for background processing
  • Flower web-based monitoring dashboard for tracking Celery task execution, worker status, and queue metrics
  • Database connection pooling through PostgreSQL with support for complex queries and transactions

Common Use Cases

  • 1SaaS platforms requiring user authentication, subscription management, and background billing processes
  • 2Data analytics APIs that need to process large datasets asynchronously while serving real-time query results
  • 3E-commerce backends handling order processing, inventory updates, and automated email notifications
  • 4Content management systems with media processing, thumbnail generation, and search indexing workflows
  • 5IoT data collection platforms aggregating sensor data with scheduled reporting and alert systems
  • 6Financial applications requiring transaction processing, compliance reporting, and automated reconciliation
  • 7Multi-tenant applications needing isolated data processing and scheduled maintenance tasks per tenant

Prerequisites

  • Docker Engine 20.10+ and Docker Compose V2 for container orchestration support
  • Minimum 2GB RAM (1GB for PostgreSQL, 512MB for Redis, 512MB for application containers)
  • Available ports 80 (Nginx), 5555 (Flower), and configurable ports for external access
  • Basic understanding of Python async/await patterns and FastAPI route decorators
  • Familiarity with PostgreSQL connection strings and Redis URL formats for environment configuration
  • Knowledge of Celery task definition syntax and worker scaling concepts

For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms

docker-compose.yml

docker-compose.yml
1services:
2 nginx:
3 image: nginx:alpine
4 container_name: fastapi-nginx
5 restart: unless-stopped
6 ports:
7 - "${NGINX_PORT:-80}:80"
8 volumes:
9 - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
10 depends_on:
11 - api
12
13 api:
14 build:
15 context: .
16 dockerfile: Dockerfile
17 container_name: fastapi-api
18 restart: unless-stopped
19 command: uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
20 volumes:
21 - ./app:/app
22 environment:
23 - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
24 - REDIS_URL=redis://redis:6379
25 - SECRET_KEY=${SECRET_KEY}
26 - ALGORITHM=HS256
27 depends_on:
28 - db
29 - redis
30
31 celery-worker:
32 build:
33 context: .
34 dockerfile: Dockerfile
35 container_name: fastapi-celery-worker
36 restart: unless-stopped
37 command: celery -A worker worker -l info -c 4
38 volumes:
39 - ./app:/app
40 environment:
41 - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
42 - REDIS_URL=redis://redis:6379
43 depends_on:
44 - db
45 - redis
46
47 celery-beat:
48 build:
49 context: .
50 dockerfile: Dockerfile
51 container_name: fastapi-celery-beat
52 restart: unless-stopped
53 command: celery -A worker beat -l info
54 volumes:
55 - ./app:/app
56 environment:
57 - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
58 - REDIS_URL=redis://redis:6379
59 depends_on:
60 - celery-worker
61
62 flower:
63 image: mher/flower:latest
64 container_name: fastapi-flower
65 restart: unless-stopped
66 ports:
67 - "${FLOWER_PORT:-5555}:5555"
68 environment:
69 - CELERY_BROKER_URL=redis://redis:6379
70 depends_on:
71 - redis
72 - celery-worker
73
74 db:
75 image: postgres:16-alpine
76 container_name: fastapi-db
77 restart: unless-stopped
78 environment:
79 - POSTGRES_USER=${DB_USER}
80 - POSTGRES_PASSWORD=${DB_PASSWORD}
81 - POSTGRES_DB=${DB_NAME}
82 volumes:
83 - postgres_data:/var/lib/postgresql/data
84
85 redis:
86 image: redis:7-alpine
87 container_name: fastapi-redis
88 restart: unless-stopped
89 volumes:
90 - redis_data:/data
91
92volumes:
93 postgres_data:
94 redis_data:

.env Template

.env
1# FastAPI Production Stack
2NGINX_PORT=80
3FLOWER_PORT=5555
4
5# Security
6SECRET_KEY=your-secret-key
7
8# Database
9DB_USER=fastapi
10DB_PASSWORD=fastapi_password
11DB_NAME=fastapi_db

Usage Notes

  1. 1FastAPI auto-generates OpenAPI docs at /docs
  2. 2Flower monitors Celery tasks at localhost:5555
  3. 3Uvicorn runs with multiple workers for concurrency
  4. 4Use Alembic for database migrations
  5. 5Redis serves as Celery broker and result backend
  6. 6Scale workers: docker compose up -d --scale celery-worker=4

Individual Services(7 services)

Copy individual services to mix and match with your existing compose files.

nginx
nginx:
  image: nginx:alpine
  container_name: fastapi-nginx
  restart: unless-stopped
  ports:
    - ${NGINX_PORT:-80}:80
  volumes:
    - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
  depends_on:
    - api
api
api:
  build:
    context: .
    dockerfile: Dockerfile
  container_name: fastapi-api
  restart: unless-stopped
  command: uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
  volumes:
    - ./app:/app
  environment:
    - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
    - REDIS_URL=redis://redis:6379
    - SECRET_KEY=${SECRET_KEY}
    - ALGORITHM=HS256
  depends_on:
    - db
    - redis
celery-worker
celery-worker:
  build:
    context: .
    dockerfile: Dockerfile
  container_name: fastapi-celery-worker
  restart: unless-stopped
  command: celery -A worker worker -l info -c 4
  volumes:
    - ./app:/app
  environment:
    - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
    - REDIS_URL=redis://redis:6379
  depends_on:
    - db
    - redis
celery-beat
celery-beat:
  build:
    context: .
    dockerfile: Dockerfile
  container_name: fastapi-celery-beat
  restart: unless-stopped
  command: celery -A worker beat -l info
  volumes:
    - ./app:/app
  environment:
    - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
    - REDIS_URL=redis://redis:6379
  depends_on:
    - celery-worker
flower
flower:
  image: mher/flower:latest
  container_name: fastapi-flower
  restart: unless-stopped
  ports:
    - ${FLOWER_PORT:-5555}:5555
  environment:
    - CELERY_BROKER_URL=redis://redis:6379
  depends_on:
    - redis
    - celery-worker
db
db:
  image: postgres:16-alpine
  container_name: fastapi-db
  restart: unless-stopped
  environment:
    - POSTGRES_USER=${DB_USER}
    - POSTGRES_PASSWORD=${DB_PASSWORD}
    - POSTGRES_DB=${DB_NAME}
  volumes:
    - postgres_data:/var/lib/postgresql/data
redis
redis:
  image: redis:7-alpine
  container_name: fastapi-redis
  restart: unless-stopped
  volumes:
    - redis_data:/data

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 nginx:
5 image: nginx:alpine
6 container_name: fastapi-nginx
7 restart: unless-stopped
8 ports:
9 - "${NGINX_PORT:-80}:80"
10 volumes:
11 - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
12 depends_on:
13 - api
14
15 api:
16 build:
17 context: .
18 dockerfile: Dockerfile
19 container_name: fastapi-api
20 restart: unless-stopped
21 command: uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
22 volumes:
23 - ./app:/app
24 environment:
25 - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
26 - REDIS_URL=redis://redis:6379
27 - SECRET_KEY=${SECRET_KEY}
28 - ALGORITHM=HS256
29 depends_on:
30 - db
31 - redis
32
33 celery-worker:
34 build:
35 context: .
36 dockerfile: Dockerfile
37 container_name: fastapi-celery-worker
38 restart: unless-stopped
39 command: celery -A worker worker -l info -c 4
40 volumes:
41 - ./app:/app
42 environment:
43 - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
44 - REDIS_URL=redis://redis:6379
45 depends_on:
46 - db
47 - redis
48
49 celery-beat:
50 build:
51 context: .
52 dockerfile: Dockerfile
53 container_name: fastapi-celery-beat
54 restart: unless-stopped
55 command: celery -A worker beat -l info
56 volumes:
57 - ./app:/app
58 environment:
59 - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
60 - REDIS_URL=redis://redis:6379
61 depends_on:
62 - celery-worker
63
64 flower:
65 image: mher/flower:latest
66 container_name: fastapi-flower
67 restart: unless-stopped
68 ports:
69 - "${FLOWER_PORT:-5555}:5555"
70 environment:
71 - CELERY_BROKER_URL=redis://redis:6379
72 depends_on:
73 - redis
74 - celery-worker
75
76 db:
77 image: postgres:16-alpine
78 container_name: fastapi-db
79 restart: unless-stopped
80 environment:
81 - POSTGRES_USER=${DB_USER}
82 - POSTGRES_PASSWORD=${DB_PASSWORD}
83 - POSTGRES_DB=${DB_NAME}
84 volumes:
85 - postgres_data:/var/lib/postgresql/data
86
87 redis:
88 image: redis:7-alpine
89 container_name: fastapi-redis
90 restart: unless-stopped
91 volumes:
92 - redis_data:/data
93
94volumes:
95 postgres_data:
96 redis_data:
97EOF
98
99# 2. Create the .env file
100cat > .env << 'EOF'
101# FastAPI Production Stack
102NGINX_PORT=80
103FLOWER_PORT=5555
104
105# Security
106SECRET_KEY=your-secret-key
107
108# Database
109DB_USER=fastapi
110DB_PASSWORD=fastapi_password
111DB_NAME=fastapi_db
112EOF
113
114# 3. Start the services
115docker compose up -d
116
117# 4. View logs
118docker compose logs -f

One-Liner

Run this command to download and set up the recipe in one step:

terminal
1curl -fsSL https://docker.recipes/api/recipes/production-fastapi-stack/run | bash

Troubleshooting

  • uvicorn.error - Application startup failed: Verify DATABASE_URL format and ensure PostgreSQL container is running before API container starts
  • celery.exceptions.NotRegistered - Task not found: Check that task functions are properly imported in worker.py and decorated with @celery.task
  • redis.exceptions.ConnectionError: Ensure Redis container is accessible and REDIS_URL environment variable matches the service name 'redis:6379'
  • nginx: [emerg] host not found in upstream: Verify API service name matches upstream configuration in nginx.conf and API container is running
  • psycopg2.OperationalError - connection limit exceeded: Increase PostgreSQL max_connections or implement connection pooling in FastAPI database configuration
  • Flower shows no workers: Confirm celery-worker container is running and CELERY_BROKER_URL in Flower matches Redis service endpoint

Community Notes

Loading...
Loading notes...

Download Recipe Kit

Get all files in a ready-to-deploy package

Includes docker-compose.yml, .env template, README, and license

Ad Space