All Dockerizers

Django Dockerfile generator

Generate a production Dockerfile for Django — Gunicorn, static files collected at build time and a non-root runtime image.

Configure

Used for the image tag, the compose service and the OCI labels.
The port the app listens on inside the container. Keep it above 1024 so the process can bind it without root.
The dotted path to your wsgi.py — usually <project>.wsgi, matching the folder next to manage.py.
A common starting point is (2 × CPU cores) + 1. Keep it low if the container has a small CPU limit.
Bakes the static files into the image so the container does not have to write to disk on boot.
Adds the database to docker-compose.yml with a healthcheck, a named volume and a DATABASE_URL wired into the app.
Adds Redis to docker-compose.yml and exposes REDIS_URL to the app.

Loading...

What this Dockerfile does

2 items need attention

  • Needs attention: Migrations do not run automatically

    Deliberately — running them on container start races when you scale past one replica. Run `python manage.py migrate` as a release step, or once via `docker compose run --rm app python manage.py migrate`.

  • Needs attention: Set ALLOWED_HOSTS and SECRET_KEY at runtime

    Django refuses requests whose Host header is not in ALLOWED_HOSTS, and will not start with DEBUG off and no SECRET_KEY. Both belong in the environment, not the image.

  • Good practice: Multi-stage build (3 stages)

    Compilers, dev dependencies and source files stay in the build stages. Only the runtime artefacts are copied into the final image.

  • Good practice: Runs as app, not root

    A container escape from a root process is a host root process. Dropping privileges is the cheapest hardening step there is.

  • Good practice: .dockerignore keeps secrets out of the build context

    `.git`, `.env` and local dependency folders never reach the daemon, so they cannot end up in a layer or in `docker history`.

  • Good practice: Dependency cache persists across builds

    BuildKit cache mounts keep the package manager store outside the image. Rebuilds after a lockfile change reuse everything already downloaded, and the cache adds nothing to the final size.

  • Good practice: Healthcheck defined

    Docker, Compose and Easypanel can tell the difference between a running process and a working app, and restart it when it wedges.

  • Good practice: Prebuilt wheels install directly

    The Debian base matches the manylinux ABI, so packages with C extensions install as prebuilt wheels instead of compiling.

  • Good practice: uv resolves from a lockfile

    `uv sync --frozen` fails if uv.lock does not match pyproject.toml, so a build can never silently drift from the versions you tested.

  • Good practice: Virtualenv copied, toolchain left behind

    The compilers and dev headers live in the deps stage. The runtime image gets the resolved virtualenv and nothing else.

  • Note: Requires BuildKit

    BuildKit is the default builder in Docker 23 and later. On anything older, export `DOCKER_BUILDKIT=1` before building.

  • Note: Gunicorn does not serve static files

    Add WhiteNoise to MIDDLEWARE so the collected files are actually served, or put nginx in front. Django's own static handling is disabled when DEBUG is off.

  • Note: Estimated image size: ~130–220 MB

    A rough band for the final stage, before your own dependencies. Run `docker images` after a build for the real number.

How to use it

Everything runs locally. Nothing is uploaded, and no account is needed.

  1. Drop the files into your project root

    Every generated file belongs next to your package manifest — the Dockerfile references paths relative to the build context, so nesting them in a subfolder breaks the COPY lines.

  2. Build the image

    docker build -t django .
  3. Run it

    docker run --rm -p 8000:8000 django
  4. Or bring up the whole stack

    docker compose up --build

Django in Docker

map illustration

Join 145,000+ self-hosters.

Free plan available. No credit card required.

Install Easypanel