Other Blog Posts

Prepare Django applications for Kubernetes using Docker multi-stage builds

2024-07-23

For production deployments Django has a concept of serving static files through a webserver rather than through the actual application. When running Django on Kubernetes you will therefore need to provide an additional webserver container, even more so since Traefik is only intended as a reverse proxy and has no built in functionality for serving static files.

Django provides the collectstatic command line utility to prepare static files for production deployment on a webserver. The filesystem location for the collectstatic output is configured with the STATIC_ROOT Django setting.

Here I'm using a Docker Multi-stage build to provide both the Django application container image and the static files. This helps me to keep the runtime images small and also makes it easier to keep the static files being served in sync with the application code.

In addition to the actual application container the build provides:

  • a custom Nginx build with static files baked into the container and alternatively
  • a tarball containing the static files made available on the build host. You can then extract the tarball in a persistent volume claim mounted into a stock Nginx container image.
FROM python:3.12-alpine as builder
RUN apk add --update xz
COPY your-django-app /opt/django
WORKDIR /opt/django
RUN python -m venv .
RUN bin/pip install -r requirements.txt
# The next line needs to match STATIC_ROOT in your settings.py
RUN mkdir /opt/static
RUN bin/python manage.py collectstatic --noinput
WORKDIR /opt
RUN tar cJf djangostatic.txz static

FROM python:3.12-alpine as djangoapp
RUN apk add --update libgcc
COPY --from=builder --chown=1000:0 /opt/django /opt/django
USER 1000
WORKDIR /opt/django
EXPOSE 8002
# change to fit your cmd line, depending e.g. on WSGI server used
CMD ["/opt/django/bin/python", "/opt/django/wsgi.py"]

FROM nginx as djangostatic
COPY --from=builder /opt/static /usr/share/nginx/html/static

FROM scratch as tarball
COPY --from=builder /opt/djangostatic.txz /djangostatic.txz

Build stages:

  • djangoapp

    The actual Django application, build with:

    podman build -t djangoapp --target djangoapp .

  • djangostatic

    Nginx webserver serving staticfiles, build with:

    podman build -t djangostatic --target djangostatic .

  • tarball

    This stage runs collectstatic and creates a tarball in the root of the container filesystem. If you have a recent buildah version or docker-buildx installed, you can then download the staticfiles archive with e.g. (docker-buildx):

    docker buildx build . --output djangostatic --target copytohost

    This will create a ./djangostatic directory on the host containing the tarball. You can then extract the tarball in a persistent volume claim mounted into a stock Nginx container image.