Docker Compose with Nginx, Django, Gunicorn, MySQL and Static File setup

Docker can be a real productivity saviour when you get to know how to use it well. It’s really great with automating deployments and even horizontally scaling your App. As you might have guessed, I actually use Docker in production for Site Monki application and I would like to share my experiences on how to set it up for production workloads.

Site Monki’s web dashboard is built on Django with MySQL db. There are a handful of tutorials online on how to setup Django with Docker, but most miss out on how to serve static files in production. Django requires a web server to serve static files such as CSS, JS, Image for the production setup while it the single-threaded development server can serve everything all with the in-built dev server. So this tutorial really is about configuring Django with Docker to serve static files.

For this purpose I use Nginx. It’s a great, lightweight web server. I use it as a reverse proxy to Docker containers running the Django app as well as a static content web server that our Django app relies on. He’s the flow;

Configuring Nginx Reverse Proxy

So we start with configuring an Nginx instance that will reverse proxy client requests to our docker fleet. We pass in all the http request header data to our Django app.

server {

   # proxy configures 
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header HOST $http_host;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header X-HTTPS-Protocol $ssl_protocol;
    proxy_set_header X-NginX-Proxy true;

    location / {



Nginx web server container

We then setup Nginx Docker container to serve static files that our Django App running on port 8000 via gunicorn generates. This Docker container will serve static assets from url to the client but proxies the rest of the queries to the Django app.

Notice we Nginx to serve static files from folder /staticfiles. We shall later map named docker volume staticfiles from our Django container to folder /staticfiles in this Nginx container using docker-compose.yml file.


FROM nginx:1.15.12-alpine

RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d

nginx.conf file

upstream mydjangoapp {
    server web:8000;

server {

    listen 80;

    location / {
        proxy_pass http://mydjangoapp;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;

    location /static/ {
        alias /staticfiles/;


Django with Gunicorn setup

Now we setup Django to collect all static files of all the apps into a single staticfiles folder in We also tell Django that the url for static files is /static

import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_DIR = os.path.join(BASE_DIR, 'static')
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')


STATIC_URL = '/static/'

We have to add gunicorn python library in a requirements.txt file. Here’s our django_mydjangoapp Dockerfile for the Django app;

FROM python:3.6.5-jessie
ENV SRC_DIR=/django_mydjangoapp
RUN mkdir -p $SRC_DIR
ADD ./requirements.txt $SRC_DIR/requirements.txt
RUN pip install -r requirements.txt

Docker-compose.yml file

We put it together in a docker-compose.yml file where we specify all our Docker containers, the ports we want to run them on and how they interact with each other.

Notice here that we have two named docker volumes; staticfiles and mysql_data. The staticfiles volume maps to actual location where our Django app puts all static assets. We then use this volume in the nginx container to serve static content. mysql_data is for persisting our app database.

version: '2.1'
      context: ./django_mydjangoapp
      dockerfile: Dockerfile
    command: bash -c "python collectstatic --no-input && python migrate && gunicorn --bind -w 4 mydjangoapp.wsgi"
      - staticfiles:/django_mydjangoapp/staticfiles
      - 8000
        condition: service_healthy
      context: ./nginx
      dockerfile: Dockerfile
      - 9090:80
      - staticfiles:/staticfiles
      - web
    image: mysql:5.7
      - 3306
      MYSQL_ROOT_PASSWORD: mydjangoapp
      MYSQL_USER: mydjangoapp
      MYSQL_PASSWORD: mydjangoapp
      MYSQL_DATABASE: mydjangoapp
      test: ["CMD", "mysqladmin", "-u$MYSQL_USER", "-p$MYSQL_PASSWORD",  "ping", "-h", "localhost"]
      timeout: 20s
      retries: 10
    restart: always
      - mysql_data:/var/lib/mysql

That’s pretty much it. Simply install Nginx in the host server and add nginx.conf in /etc/nginx/sites-available/ then run docker-compose up in our app folder.