Understanding Django Production Architecture
app: build: . command: gunicorn myproject.wsgi:application --workers 4 --bind 0.0.0.0:8000 env_file: .env volumes: - .:/app expose: - "8000" depends_on: - db - redis
db: image: postgres:14-alpine environment: POSTGRES_DB: mydb POSTGRES_USER: myuser POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data
redis: image: redis:6-alpine volumes: - redis_data:/data
volumes: static_volume: media_volume: postgres_data: redis_data: </code></pre>
<p>Even if you choose a VM‑based deployment, the logical separation described above remains the same.</p>Configuring the Server Environment
DEBUG = False ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', 'example.com').split(',')
Database - use PostgreSQL via environment variables
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.getenv('POSTGRES_DB'), 'USER': os.getenv('POSTGRES_USER'), 'PASSWORD': os.getenv('POSTGRES_PASSWORD'), 'HOST': os.getenv('POSTGRES_HOST', 'localhost'), 'PORT': os.getenv('POSTGRES_PORT', '5432'), } }
Static & Media files - served by Nginx
STATIC_ROOT = os.path.join(BASE_DIR, 'static/') MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
Security settings
SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True X_FRAME_OPTIONS = 'DENY'
Logging - JSON for easy ingestion by ELK or Loki
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'json': { '()': 'pythonjsonlogger.jsonlogger.JsonFormatter', 'fmt': '%(asctime)s %(levelname)s %(name)s %(message)s', }, }, 'handlers': { 'file': { 'class': 'logging.FileHandler', 'filename': '/opt/django_app/logs/django.json', 'formatter': 'json', }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'), }, }, } </code></pre>
<p>Export the path to this settings module when starting Gunicorn:</p> <pre><code>export DJANGO_SETTINGS_MODULE=myproject.settings_production </code></pre> <h3>5. Deploy Gunicorn as a Systemd Service</h3> <p>Systemd monitors the process, restarts it on failure, and integrates with logrotate.</p> <pre><code>[Unit] Description=Gunicorn daemon for Django project After=network.target[Service]
User=django_user
Group=django_user
WorkingDirectory=/opt/django_app
Environment="PATH=/opt/django_app/venv/bin"
ExecStart=/opt/django_app/venv/bin/gunicorn myproject.wsgi:application
--workers 4
--bind unix:/opt/django_app/run/gunicorn.sock
Restart=on-failure
[Install] WantedBy=multi-user.target </code></pre>
<p>Enable and start the service:</p> <pre><code>sudo systemctl daemon-reload sudo systemctl enable gunicorn sudo systemctl start gunicorn </code></pre> <h3>6. Configure Nginx as a Reverse Proxy</h3> <p>Create <code>/etc/nginx/sites-available/django.conf</code> and enable it.</p> <pre><code>server { listen 80; server_name example.com www.example.com;# Enforce HTTPS - let Certbot handle certs later
return 301 https://$host$request_uri;
}
server { listen 443 ssl http2; server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Static files
location /static/ {
alias /opt/django_app/static/;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
location /media/ {
alias /opt/django_app/media/;
}
# Proxy to Gunicorn via Unix socket
location / {
proxy_pass http://unix:/opt/django_app/run/gunicorn.sock;
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;
}
} </code></pre>
<p>Enable the site and reload Nginx:</p> <pre><code>sudo ln -s /etc/nginx/sites-available/django.conf /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx </code></pre> <h3>7. Obtain and Auto‑Renew TLS Certificates</h3> <p>Let’s Encrypt provides free certificates. Install Certbot and run:</p> <pre><code>sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d example.com -d www.example.com </code></pre> <p>The tool automatically updates the Nginx config and sets up a systemd timer for renewal.</p>Security, Scaling, and Monitoring Best Practices
@cache_page(60 * 15) # Cache for 15 minutes def homepage(request): return render(request, 'home.html') </code></pre>
<ul> <li><strong>Asynchronous Tasks</strong>: Offload long‑running jobs to Celery workers that consume messages from RabbitMQ or Redis.</li> </ul> <h3>Observability Stack</h3> <p>Collect logs, metrics, and traces to detect anomalies early.</p> <ul> <li><strong>Logging</strong>: Ship <code>/opt/django_app/logs/*.json</code> to Loki or Elastic via Filebeat.</li> <li><strong>Metrics</strong>: Expose Prometheus metrics with <code>django‑prometheus</code> and scrape them via <code>node_exporter</code>.</li> <li><strong>Tracing</strong>: Integrate OpenTelemetry SDK and send traces to Jaeger.</li> </ul> <pre><code># Example of OpenTelemetry init in Django import opentelemetry.instrumentation.django from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.jaeger.thrift import JaegerExportertrace.set_tracer_provider(TracerProvider()) jaeger_exporter = JaegerExporter( agent_host_name='jaeger', agent_port=6831, ) trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(jaeger_exporter) ) opentelemetry.instrumentation.django.DjangoInstrumentor().instrument() </code></pre>
<h3>Automated Backups & Disaster Recovery</h3> <p>Schedule daily logical backups with <code>pg_dump</code> and store them in encrypted S3 buckets. Test point‑in‑time recovery quarterly.</p> <pre><code>0 2 * * * /usr/bin/pg_dump -U myuser mydb | gzip > /backups/mydb_$(date +\%F).sql.gz aws s3 cp /backups/ s3://my‑prod‑backups/ --recursive --storage-class GLACIER </code></pre> <p>By combining these measures, you achieve a resilient, secure, and scalable Django production environment.</p>