Production-ready Django deployment with Gunicorn and high-performance Uvicorn workers in Docker.
- Python: 3.13
- Django: 5.2.8 (LTS)
- Gunicorn: 23.0.0
- Uvicorn: 0.38.0 (ASGI worker with uvloop and httptools)
- Supervisor: 4.3.0
- ASGI/WSGI compatible Django application
- High-performance Uvicorn workers with uvloop and httptools
- Gunicorn as HTTP server
- Supervisor for process management
- Docker Compose for easy deployment
- Development and production settings separation
- Security headers configured
- Lightweight architecture without nginx overhead
cd django_gunicorn
python3 manage.py runserver --settings=django_gunicorn.settings.development# Build and start containers
docker-compose up --build
# Access the application at http://localhost:8000
# Admin interface at http://localhost:8000/admindocker-compose downdocker build -t django-gunicorn:latest .# Run on port 8000
docker run -it -d --rm -p 8000:8000 django-gunicorn:latest
# Access at http://localhost:8000The application supports different environment configurations:
- Development:
django_gunicorn.settings.development - Production:
django_gunicorn.settings.product
Set the environment using the SERVICE_ARG build argument:
docker build --build-arg SERVICE_ARG=product -t django-gunicorn:prod .Located at deploy_tools/gunicorn_conf.py:
- Bind address:
0.0.0.0:8000 - Worker class: Custom Uvicorn worker with uvloop and httptools
- Workers:
(CPU cores * 2) + 1 - Max requests: 1000 (with jitter)
- Timeout: 15 seconds
- Keepalive: 62 seconds
This project uses a simplified architecture without nginx:
Client → Gunicorn (port 8000) → Uvicorn Workers → Django App
Why no nginx?
- Simpler architecture with fewer moving parts
- Lower resource usage (memory and CPU)
- Easier to maintain and debug
- Gunicorn + Uvicorn workers provide excellent performance for most use cases
- For production with nginx, you can add it as a reverse proxy in front of this container
.
├── django_gunicorn/
│ ├── django_gunicorn/
│ │ ├── settings/
│ │ │ ├── settings_base.py
│ │ │ ├── development.py
│ │ │ └── product.py
│ │ ├── urls.py
│ │ ├── asgi.py
│ │ └── wsgi.py
│ ├── sample_app/
│ └── manage.py
├── deploy_tools/
│ ├── gunicorn_conf.py # Gunicorn configuration
│ ├── workers.py # Custom Uvicorn worker
│ └── supervisor.conf # Supervisor process manager config
├── requirements/
│ └── requirements.txt
├── Dockerfile
└── docker-compose.yaml
The production settings (django_gunicorn.settings.product) include:
DEBUG = False- Security middleware enabled
- Proper logging configuration
- Static and media files configuration
- Security headers (X-Frame-Options, X-Content-Type-Options, etc.)
-
Environment Variables
docker build --build-arg SERVICE_ARG=product -t django-gunicorn:prod . -
Security Configuration
- Set
SECRET_KEYvia environment variable - Configure
ALLOWED_HOSTSwith your domain - Enable HTTPS settings if using SSL/TLS
- Set
-
Database Setup
docker exec <container-name> python manage.py migrate
-
Static Files
docker exec <container-name> python manage.py collectstatic --noinput
-
Optional: Add Nginx Reverse Proxy
For production with SSL termination and static file serving, you can add nginx as a reverse proxy:
server { listen 80; server_name yourdomain.com; location / { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
With Gunicorn + Uvicorn workers (uvloop + httptools):
- Response Time: ~4-8ms average
- Workers: Auto-scaled based on CPU cores
(cores * 2) + 1 - Concurrent Connections: 1000 per worker
- Protocol: HTTP/1.1 with keepalive
This setup provides excellent performance for most applications without the complexity of nginx.
This project is open source and available for educational purposes.