Serving with gunicorn

1) Django development server can process only one request at a time

2) Therefore, we ll replace the default develpment server with gunicorn. (Other options for django servers : Mod_WSGI, uWSGI)

3) To use gunicorn, add the following requirement

gunicorn==19.9.0

4) Replace python manage.py runserver 0.0.0.0:8000 with gunicorn running 4 worker threads

gunicorn -w 4 APP_NAME.wsgi -b 0.0.0.0:8000

NOTE : Point gunicorn to the wsgi.py file under the project directory

Serving static contents

1) Gunicorn does not serve static contents like images (It serves JS, CSS)

2) If static contents are present, it has to be processed by nginx

Steps to serve static files with nginx:

1) Set STATIC_ROOT in settings.py (say /vol/static)

2) Run

python manage.py collectstatic
# collects all static files at /vol/static

3) Point the STATIC_URL (say /static) to STATIC_ROOT (say /vol/static) in nginx server config

location /static {
        # root /vol/; (or)
        alias /vol/static;
    }

NOTE: Pointing folder from one container (django) to another (nginx) without creating it in the host can be done with docker volumes (see the docker-compose.yml for example)

servers.conf

server {
    listen 80;
    server_name localhost;

    location / {
        try_files $uri $uri/ @python_django;
    }

    location /static {
        # root /vol/; (or)
        alias /vol/static;
    }

    location @python_django {
        proxy_pass http://app:8000;
        proxy_pass_request_headers on;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off;
    }
}

docker-compose.yml

yml
version: "3"

services:
    app:
      build:
        context: .
        dockerfile: Docker/prod/Dockerfile
      ports:
        - "8000:8000"
      volumes:
        - ./app:/app
        # this volume is created when collectstatic command is run
        # set static_root = /vol/static in settings.py
        - static_files:/vol/static
      command: >
        sh -c "python manage.py collectstatic --noinput &&
               python manage.py migrate &&
               gunicorn -w 4 app.wsgi -b 0.0.0.0:8000"

    nginx:
      build:
        context: .
        dockerfile: Docker/prod/nginx/Dockerfile
      ports:
        - "80:80"
      volumes:
        # app creates a docker volume, which is inturn mapped here
        - static_files:/vol/static
        - ${PWD}/Docker/prod/nginx/servers.conf:/etc/nginx/conf.d/servers.conf

volumes:
  # gets created when collectstatic command is run
  # because of internal mapping, we never see this folder outside
  static_files:

Full Code:

See nginx-django folder