Django ist das populärste Python-Webframework. Für den Produktionsbetrieb benötigt es einen WSGI-Server wie Gunicorn und einen Reverse Proxy wie Nginx.
Architektur
Production-Stack
Client → Nginx (Port 80/443)
↓
Gunicorn (Unix Socket)
↓
Django App
↓
PostgreSQLVorbereitung
Python installieren
apt install python3 python3-pip python3-venvProjekt-Verzeichnis
mkdir -p /var/www/myproject
cd /var/www/myprojectVirtual Environment
python3 -m venv venv
source venv/bin/activateDjango-Projekt
Installation
pip install django gunicorn psycopg2-binaryNeues Projekt erstellen
django-admin startproject myproject .
# Oder bestehendes klonen
git clone https://github.com/user/myproject.git .
pip install -r requirements.txtSettings anpassen
# myproject/settings.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# Security
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
DEBUG = os.environ.get('DJANGO_DEBUG', 'False') == 'True'
ALLOWED_HOSTS = ['example.de', 'www.example.de']
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'myproject'),
'USER': os.environ.get('DB_USER', 'myproject'),
'PASSWORD': os.environ.get('DB_PASSWORD'),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
# Static files
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# Security headers
if not DEBUG:
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
X_FRAME_OPTIONS = 'DENY'Datenbank einrichten
# PostgreSQL
sudo -u postgres psql
CREATE DATABASE myproject;
CREATE USER myproject WITH PASSWORD 'sicheres_passwort';
ALTER ROLE myproject SET client_encoding TO 'utf8';
ALTER ROLE myproject SET default_transaction_isolation TO 'read committed';
ALTER ROLE myproject SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE myproject TO myproject;
\q
# Migrationen
source venv/bin/activate
python manage.py migrate
python manage.py collectstatic --noinput
python manage.py createsuperuserGunicorn
Konfiguration
# /var/www/myproject/gunicorn.conf.py
import multiprocessing
bind = "unix:/run/gunicorn/myproject.sock"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync"
worker_connections = 1000
timeout = 30
keepalive = 2
user = "www-data"
group = "www-data"
errorlog = "/var/log/gunicorn/myproject-error.log"
accesslog = "/var/log/gunicorn/myproject-access.log"
loglevel = "info"
proc_name = "myproject"Systemd-Service
# /etc/systemd/system/gunicorn-myproject.service
[Unit]
Description=Gunicorn daemon for myproject
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myproject
RuntimeDirectory=gunicorn
Environment="DJANGO_SECRET_KEY=dein_secret_key"
Environment="DJANGO_DEBUG=False"
Environment="DB_PASSWORD=dein_db_passwort"
ExecStart=/var/www/myproject/venv/bin/gunicorn \
--config /var/www/myproject/gunicorn.conf.py \
myproject.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetService starten
mkdir -p /var/log/gunicorn
chown www-data:www-data /var/log/gunicorn
systemctl daemon-reload
systemctl enable gunicorn-myproject
systemctl start gunicorn-myprojectNginx
Konfiguration
# /etc/nginx/sites-available/myproject
upstream myproject {
server unix:/run/gunicorn/myproject.sock fail_timeout=0;
}
server {
listen 80;
server_name example.de www.example.de;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.de www.example.de;
ssl_certificate /etc/letsencrypt/live/example.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.de/privkey.pem;
client_max_body_size 10M;
access_log /var/log/nginx/myproject-access.log;
error_log /var/log/nginx/myproject-error.log;
location /static/ {
alias /var/www/myproject/staticfiles/;
expires 30d;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /var/www/myproject/media/;
expires 7d;
}
location / {
proxy_pass http://myproject;
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;
proxy_redirect off;
}
}Aktivieren
ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginxUmgebungsvariablen
.env-Datei
# /var/www/myproject/.env
DJANGO_SECRET_KEY=dein_sehr_langes_secret_key_hier
DJANGO_DEBUG=False
DB_NAME=myproject
DB_USER=myproject
DB_PASSWORD=sicheres_passwort
DB_HOST=localhost
DB_PORT=5432python-dotenv
# myproject/settings.py
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')Systemd Environment
# /etc/systemd/system/gunicorn-myproject.service.d/override.conf
[Service]
EnvironmentFile=/var/www/myproject/.envCelery (Background Tasks)
Installation
pip install celery redisKonfiguration
# myproject/celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()# myproject/settings.py
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'Celery-Service
# /etc/systemd/system/celery-myproject.service
[Unit]
Description=Celery Worker for myproject
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myproject
EnvironmentFile=/var/www/myproject/.env
ExecStart=/var/www/myproject/venv/bin/celery \
-A myproject worker \
--loglevel=INFO \
--concurrency=4
Restart=on-failure
[Install]
WantedBy=multi-user.targetDeployment-Skript
#!/bin/bash
# /var/www/myproject/deploy.sh
set -e
cd /var/www/myproject
# Git Pull
git pull origin main
# Virtual Environment
source venv/bin/activate
# Dependencies
pip install -r requirements.txt
# Migrationen
python manage.py migrate --noinput
# Static Files
python manage.py collectstatic --noinput
# Services neu starten
sudo systemctl restart gunicorn-myproject
sudo systemctl restart celery-myproject
echo "Deployment abgeschlossen"chmod +x /var/www/myproject/deploy.shLogging
Django Logging
# myproject/settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
},
'handlers': {
'file': {
'level': 'WARNING',
'class': 'logging.FileHandler',
'filename': '/var/log/django/myproject.log',
'formatter': 'verbose',
},
},
'root': {
'handlers': ['file'],
'level': 'WARNING',
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'WARNING',
'propagate': False,
},
},
}Monitoring
Django Health Check
pip install django-health-check# settings.py
INSTALLED_APPS = [
# ...
'health_check',
'health_check.db',
'health_check.cache',
'health_check.storage',
]
# urls.py
urlpatterns = [
path('health/', include('health_check.urls')),
]Sentry
pip install sentry-sdk# settings.py
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
if not DEBUG:
sentry_sdk.init(
dsn="https://xxx@sentry.io/xxx",
integrations=[DjangoIntegration()],
traces_sample_rate=0.1,
)Sicherheit
Checkliste
# Django Security Check
python manage.py check --deploySecurity-Einstellungen
# settings.py (Production)
# HTTPS
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Cookies
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
# Headers
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'
# HSTS
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = TrueZusammenfassung
| Komponente | Funktion | |------------|----------| | Django | Webframework | | Gunicorn | WSGI-Server | | Nginx | Reverse Proxy | | PostgreSQL | Datenbank | | Redis | Cache/Celery Broker | | Celery | Background Tasks |
| Befehl | Funktion | |--------|----------| | python manage.py migrate | Datenbank-Migration | | python manage.py collectstatic | Static Files sammeln | | python manage.py check --deploy | Security-Check |
| Datei | Funktion | |-------|----------| | /var/www/myproject/ | Projekt-Root | | /etc/systemd/system/gunicorn-*.service | Service-Definition | | /etc/nginx/sites-available/ | Nginx-Config |
Fazit
Ein Django-Deployment erfordert mehrere Komponenten, die zusammenarbeiten müssen. Gunicorn als WSGI-Server ist performant und einfach zu konfigurieren. Nginx übernimmt SSL-Terminierung und statische Dateien. Umgebungsvariablen trennen Konfiguration vom Code. Mit Celery lassen sich zeitintensive Aufgaben auslagern. Regelmäßige Updates und Security-Checks sind für den Produktionsbetrieb essentiell.