A project that runs happily under runserver still needs a few changes before it can go live: production settings, collected static files, a production application server and a reverse proxy in front of it. This chapter goes through those steps in order and shows a common setup.
Production settings
Check these settings before every deployment.
# mysite/settings.py (production-relevant parts)
import os
DEBUG = False
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
ALLOWED_HOSTS = ["example.com", "www.example.com"]
CSRF_TRUSTED_ORIGINS = ["https://example.com", "https://www.example.com"]
STATIC_ROOT = BASE_DIR / "staticfiles"
# HTTPS
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 3600
Only enable SECURE_PROXY_SSL_HEADER when your proxy always sets X-Forwarded-Proto and overwrites any value sent by the client. Start HSTS with a short duration and raise it once everything works. When you are done, let Django look for anything you missed:
DJANGO_SECRET_KEY=... python manage.py check --deploy
With DEBUG = False, Django stops serving static files itself. Run collectstatic to copy every app's static/ files into STATIC_ROOT, then let a web server such as Nginx, or a CDN, serve that folder.
python manage.py collectstatic --noinput
python manage.py migrate --noinput
If running a separate web server is inconvenient, add the WhiteNoise package as middleware so the Python process can serve static files efficiently. Keep user uploads (MEDIA_ROOT) separate from static files, and when you run several servers, point the STORAGES setting at an object store such as S3.
WSGI and ASGI servers
The wsgi.py and asgi.py files created by startproject each expose an application object. For mostly synchronous views, use a WSGI server such as Gunicorn. If you need async views or WebSockets (Django Channels), use an ASGI server such as Uvicorn or Daphne.
python -m pip install gunicorn uvicorn
# WSGI with four worker processes
gunicorn mysite.wsgi --workers 4 --bind 127.0.0.1:8000
# ASGI with Uvicorn on its own
uvicorn mysite.asgi:application --host 127.0.0.1 --port 8000 --workers 4
Start with a worker count based on your CPU cores and tune it under real load. Run the server under a process manager such as systemd, Supervisor or a container orchestrator, so it restarts after a crash.
Reverse proxy
Put a reverse proxy such as Nginx in front of the application server. The proxy terminates TLS, serves static files and buffers slow clients, and forwards only dynamic requests to Gunicorn.
server {
listen 443 ssl;
server_name example.com;
location /static/ {
alias /srv/mysite/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Deploying with containers
Containers give every server an identical environment. Keep secrets out of the image and pass them in as environment variables at run time.
FROM python:3-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN DJANGO_SECRET_KEY=build-only python manage.py collectstatic --noinput
CMD ["gunicorn", "mysite.wsgi", "--bind", "0.0.0.0:8000", "--workers", "4"]
Run migrations once as a deployment step, not while building the image. In production, collect errors through the LOGGING setting and get notified about exceptions via ADMINS or a service such as Sentry.
Summary
- Set
DEBUG = False, a secret SECRET_KEY and ALLOWED_HOSTS, then verify with check --deploy. - Gather static files with
collectstatic and serve them from a web server or WhiteNoise. - Run the app with Gunicorn (WSGI) or Uvicorn (ASGI) behind a reverse proxy such as Nginx.
- Run migrations as part of the deployment and set up logging and error reporting.
Official documentation
0 条评论
登录 · 登录后即可发表评论。