docker.recipes

Django + PostgreSQL

intermediate

Python Django web framework with PostgreSQL database.

Overview

Django is a high-level Python web framework that follows the "batteries-included" philosophy, providing developers with built-in authentication, admin interface, ORM, and security features out of the box. Created in 2005 for newspaper websites, Django has evolved into one of the most popular web frameworks, powering sites like Instagram, Pinterest, and Mozilla. Its emphasis on rapid development, clean pragmatic design, and the DRY (Don't Repeat Yourself) principle makes it ideal for content-heavy applications and complex data-driven websites. This stack combines Django's robust web framework with PostgreSQL's advanced relational database capabilities and NGINX's high-performance web serving. Django's ORM leverages PostgreSQL's ACID compliance, JSON support, and advanced indexing for complex queries, while NGINX handles static file serving and acts as a reverse proxy to Gunicorn, Django's WSGI server. This architecture separates concerns effectively: NGINX handles HTTP connections and static content, Gunicorn manages Python application processes, and PostgreSQL provides reliable data persistence with advanced features like full-text search and geospatial data support. This combination is perfect for Python developers building content management systems, e-commerce platforms, social media applications, or any data-intensive web application requiring user authentication and complex database relationships. The stack scales well from prototype to production, with PostgreSQL's replication capabilities and NGINX's load balancing supporting growth from single-server deployments to distributed architectures.

Key Features

  • Django's built-in admin interface with PostgreSQL's rich data types for complex content management
  • PostgreSQL's JSONB support integrated with Django's JSONField for hybrid relational-document data models
  • NGINX static file serving with Django's collectstatic management for optimized asset delivery
  • Gunicorn WSGI server with multiple worker processes for concurrent request handling
  • PostgreSQL's full-text search capabilities accessible through Django's search framework
  • NGINX reverse proxy with connection pooling to Gunicorn upstream servers
  • Django's migration system leveraging PostgreSQL's transactional DDL for safe schema changes
  • PostgreSQL's advanced indexing (GIN, GiST, partial) optimized through Django's database introspection

Common Use Cases

  • 1Content management systems requiring complex taxonomies and full-text search capabilities
  • 2E-commerce platforms needing ACID-compliant transactions and inventory management
  • 3Social media applications with user-generated content and complex relationship modeling
  • 4Enterprise web applications requiring Django's built-in authentication and permissions system
  • 5Data analytics dashboards leveraging PostgreSQL's window functions and Django's ORM
  • 6Multi-tenant SaaS applications using PostgreSQL's row-level security with Django's middleware
  • 7GIS applications combining Django's GeoDjango with PostgreSQL's PostGIS extension

Prerequisites

  • Docker Engine and Docker Compose installed on host system
  • Minimum 1.5GB RAM (512MB for PostgreSQL, 256MB for NGINX, 512MB for Django/Gunicorn, plus OS overhead)
  • Python and Django development knowledge for application customization
  • PostgreSQL query optimization understanding for production database tuning
  • Port 80 available for NGINX HTTP traffic
  • Basic understanding of WSGI deployment patterns and Gunicorn configuration

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 web:
3 build: .
4 container_name: django
5 command: gunicorn myproject.wsgi:application --bind 0.0.0.0:8000
6 volumes:
7 - static_volume:/app/staticfiles
8 environment:
9 DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
10 SECRET_KEY: ${SECRET_KEY}
11 depends_on:
12 - postgres
13 networks:
14 - django
15
16 postgres:
17 image: postgres:16-alpine
18 container_name: postgres
19 environment:
20 POSTGRES_DB: ${DB_NAME}
21 POSTGRES_USER: ${DB_USER}
22 POSTGRES_PASSWORD: ${DB_PASSWORD}
23 volumes:
24 - postgres_data:/var/lib/postgresql/data
25 networks:
26 - django
27
28 nginx:
29 image: nginx:alpine
30 container_name: nginx
31 volumes:
32 - static_volume:/app/staticfiles:ro
33 - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
34 ports:
35 - "80:80"
36 depends_on:
37 - web
38 networks:
39 - django
40
41volumes:
42 postgres_data:
43 static_volume:
44
45networks:
46 django:
47 driver: bridge

.env Template

.env
1DB_NAME=django
2DB_USER=django
3DB_PASSWORD=changeme
4SECRET_KEY=your-secret-key

Usage Notes

  1. 1Docs: https://docs.djangoproject.com/
  2. 2Create Dockerfile with Python + gunicorn
  3. 3Run migrations: docker compose exec web python manage.py migrate
  4. 4Collect static: docker compose exec web python manage.py collectstatic
  5. 5Create superuser: docker compose exec web python manage.py createsuperuser
  6. 6Configure nginx/nginx.conf to proxy to gunicorn and serve static files

Individual Services(3 services)

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

web
web:
  build: .
  container_name: django
  command: gunicorn myproject.wsgi:application --bind 0.0.0.0:8000
  volumes:
    - static_volume:/app/staticfiles
  environment:
    DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
    SECRET_KEY: ${SECRET_KEY}
  depends_on:
    - postgres
  networks:
    - django
postgres
postgres:
  image: postgres:16-alpine
  container_name: postgres
  environment:
    POSTGRES_DB: ${DB_NAME}
    POSTGRES_USER: ${DB_USER}
    POSTGRES_PASSWORD: ${DB_PASSWORD}
  volumes:
    - postgres_data:/var/lib/postgresql/data
  networks:
    - django
nginx
nginx:
  image: nginx:alpine
  container_name: nginx
  volumes:
    - static_volume:/app/staticfiles:ro
    - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
  ports:
    - "80:80"
  depends_on:
    - web
  networks:
    - django

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 web:
5 build: .
6 container_name: django
7 command: gunicorn myproject.wsgi:application --bind 0.0.0.0:8000
8 volumes:
9 - static_volume:/app/staticfiles
10 environment:
11 DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_NAME}
12 SECRET_KEY: ${SECRET_KEY}
13 depends_on:
14 - postgres
15 networks:
16 - django
17
18 postgres:
19 image: postgres:16-alpine
20 container_name: postgres
21 environment:
22 POSTGRES_DB: ${DB_NAME}
23 POSTGRES_USER: ${DB_USER}
24 POSTGRES_PASSWORD: ${DB_PASSWORD}
25 volumes:
26 - postgres_data:/var/lib/postgresql/data
27 networks:
28 - django
29
30 nginx:
31 image: nginx:alpine
32 container_name: nginx
33 volumes:
34 - static_volume:/app/staticfiles:ro
35 - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
36 ports:
37 - "80:80"
38 depends_on:
39 - web
40 networks:
41 - django
42
43volumes:
44 postgres_data:
45 static_volume:
46
47networks:
48 django:
49 driver: bridge
50EOF
51
52# 2. Create the .env file
53cat > .env << 'EOF'
54DB_NAME=django
55DB_USER=django
56DB_PASSWORD=changeme
57SECRET_KEY=your-secret-key
58EOF
59
60# 3. Start the services
61docker compose up -d
62
63# 4. View logs
64docker 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/django-postgres/run | bash

Troubleshooting

  • django.db.utils.OperationalError: could not connect to server: Ensure PostgreSQL container is fully started before Django migrations run
  • NGINX 502 Bad Gateway errors: Check that Gunicorn is binding to 0.0.0.0:8000 not localhost:8000 for inter-container communication
  • Static files not loading (404 errors): Run 'docker compose exec web python manage.py collectstatic' and verify NGINX volume mount for staticfiles
  • PostgreSQL connection pool exhausted: Tune Django's CONN_MAX_AGE setting and PostgreSQL's max_connections parameter based on Gunicorn worker count
  • Django migrations hanging: Check PostgreSQL logs for lock conflicts and ensure proper migration ordering in apps
  • NGINX upstream timeout errors: Increase proxy_read_timeout in NGINX config for long-running Django views or background tasks

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