Skip to content

Instantly share code, notes, and snippets.

@dungdm93 dungdm93/
Last active Jul 7, 2019

What would you like to do?
Django serve staticfiles

Django Staticfiles

Django staticfiles is the most common problem you need to solve before putting your app on the production. In this tutorial, I and you will walk through the solution options, included.

  • runserver: Only in development environment.
  • gunicorn: Use gunicorn as your app server.
  • nginx: Put nginx web server in a front of your app server (gunicorn).
  • whitenoise: Let your django app self-serve static files.


Goto session 4: whitenoise


In order to python runserver serve staticfiles, bellow configs are required:

  1. In

    DEBUG = True

That's all. However, runserver should never used in production because of performance reasons.


In production environment, you should use gunicorn as Python WSGI HTTP Server. However, in order to gunicorn serve static files, you need some extra configs:

  1. Enable debug mode

    DEBUG = True
  2. Configs STATIC_ROOT and urlpatterns

    # Static files (CSS, JavaScript, Images)
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    from django.conf.urls.static import static
    from . import settings
    urlpatterns = [ ... ]
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
  3. Collect statics files, by running this command:

    python collectstatic

Now, run gunicorn YOUR_APP.wsgi to see the result.


gunicorn is a good App Server, but enable DEBUG mode is not recommended in production. One option is put a Web Server like NginX, Apache HTTPD,... in front of gunicorn and let it serve your static files.

1. NginX

upstream app_server {
    # fail_timeout=0 means we always retry an upstream even if it failed
    # to return a good HTTP response

    # for a TCP configuration
    server fail_timeout=0;

    # for UNIX domain socket setups
    # server unix:/run/gunicorn.sock fail_timeout=0;

server {
    listen 80;

    keepalive_timeout 5;
    client_max_body_size 4G;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /absolute/path/to/your/static/dir;

    location / {
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host  $server_name;
        proxy_set_header X-Real-IP         $remote_addr;

        proxy_pass http://app_server;

    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /absolute/path/to/your/static/dir;


NginX/Apache HTTPD work every well in VM world. If your deployment environment use container technologies like Docker and Kubernetes, it become bulky and hard to config. Recently, I discovered a lighter alternative solution call whitenoise

  1. Install

    pip install whitenoise

    or, add it into requirements.txt

  2. add WhiteNoise to the MIDDLEWARE_CLASSES list


    Note: WhiteNoiseMiddleware must be above all other middleware apart from Django’s SecurityMiddleware.

  3. Configs STATIC_ROOT

    # Static files (CSS, JavaScript, Images)
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
  4. And you still need collect statics files

    python collectstatic

That's it. Now you can run whatever app server you want, somethings like:

python runserver
# or
gunicorn YOUR_APP.wsgi # change YOUR_APP to your real app


  1. Dockerfile

    FROM python:3.6
    LABEL maintainer="Development Team<>"
    WORKDIR /app
    EXPOSE 8000
    ADD requirements.txt /app/requirements.txt
    RUN pip install --no-cache-dir -r requirements.txt
    ADD . /app
    RUN python collectstatic --no-input
    CMD [ "gunicorn", "YOUR_APP.wsgi", "--bind=" ]
  2. docker-compose.yml

    version: "3.5"
        build: .
        # Change image if you prefer different name
        image: django/demo:dev
        # Override command in Dockerfile for development environment
        command: [ "python", "", "runserver", "" ]
        - 8000:8000
        # Mount source code for hot reload
        - .:/app
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.