← Zurück zum Blog
DockerDjango12. April 2026· 16 min Lesezeit

Docker + Django: Produktionsreife Entwicklungsumgebung aufsetzen

Inhalt
  1. Das Dockerfile
  2. docker-compose für Entwicklung
  3. Nginx + Gunicorn für Produktion
  4. Umgebungsvariablen
  5. Multi-Stage Builds
  6. Praxis-Tipps

"Works on my machine" ist in professionellen Teams keine Option. Mit Docker läuft deine Django-Anwendung überall identisch — von der lokalen Entwicklung über CI/CD bis zur Produktion.

Das Dockerfile

FROM python:3.12-slim AS base

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

WORKDIR /app

RUN apt-get update && apt-get install -y \
    libpq-dev gcc \
    && rm -rf /var/lib/apt/lists/*

# Erst requirements kopieren (besseres Caching!)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Dann den Code
COPY . .
RUN python manage.py collectstatic --noinput

docker-compose für die Entwicklung

services:
  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword

  redis:
    image: redis:7-alpine

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/app    # Live-Reload
    ports: ["8000:8000"]
    env_file: .env
    depends_on: [db, redis]

  celery:
    build: .
    command: celery -A myproject worker -l info
    volumes: [".:/app"]
    env_file: .env
    depends_on: [db, redis]

volumes:
  postgres_data:

Nginx + Gunicorn für Produktion

services:
  web:
    build: .
    command: gunicorn myproject.wsgi:application \
      --bind 0.0.0.0:8000 --workers 4 --threads 2 --timeout 120
    expose: ["8000"]
    volumes: [static_files:/app/staticfiles]

  nginx:
    image: nginx:alpine
    ports: ["80:80", "443:443"]
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
      - static_files:/staticfiles
    depends_on: [web]
# nginx.conf
upstream django { server web:8000; }

server {
    listen 80;
    location /static/ {
        alias /staticfiles/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    location / {
        proxy_pass http://django;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Umgebungsvariablen richtig handhaben

# .env (nicht in Git!)
DEBUG=True
SECRET_KEY=dev-secret-key
DATABASE_URL=postgres://myuser:mypassword@db:5432/mydb
REDIS_URL=redis://redis:6379/0
ALLOWED_HOSTS=localhost,127.0.0.1
# settings.py
import environ

env = environ.Env(DEBUG=(bool, False))
environ.Env.read_env()

DEBUG = env("DEBUG")
SECRET_KEY = env("SECRET_KEY")
DATABASES = {"default": env.db()}

Multi-Stage Builds für kleinere Images

FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --prefix=/install --no-cache-dir -r requirements.txt

# Runtime-Stage
FROM python:3.12-slim AS runtime
COPY --from=builder /install /usr/local
WORKDIR /app
COPY . .
RUN python manage.py collectstatic --noinput
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

Praxis-Tipps

Yevhen Chubchyk
Yevhen Chubchyk
Senior Python / Django Entwickler · Freelancer seit 2016 · 20+ Jahre IT-Erfahrung. Kunden: Siemens Healthineers, Engie, natureOffice u.a.