Thursday 10 November 2011

Serving Django as a Nginx & Supervisord Sandwich with a Gunicorn Filling.

When serving Django it’s easy to feel like there are too many technologies involved. At first it’s hard to know which parts do what. In an attempt to straighten out some confusion for you this post outlines how I do it.

At the heart of this setup there are three technologies and they’re organised like a sandwich.

Django App Sandwich


Like Apache and Lighttpd, Nginx is a web server.

In the diagram above nginx is the web public facing web server that responds to HTTP requests from the outside world. In this setup nginx has two jobs.

  1. To serve HTTP requests for the static media for a project’s static media (normally on a domain such as http(s)://

  2. To act as a proxy for HTTP requests for the application and to return the HTTP response.

Nginx is the top slice of bread.

The Django Project

The django project is mixture of source code, a virtual environment, configuration files and static media. I’ll go into more depth about this in a blog post at some point in the future.

The django projects are run using green unicorn (gunicorn). It is a Python WSGI HTTP Server for UNIX. When you’re working on your projects on your local development machine, you’ll this command to serve the project—

/path/to/python /path/to/project/ runserver

However you’re strongly warned against using the development server for production work. So we’re using gunicorn to serve the project; the command to do so looks very familiar —

/path/to/python /path/to/project/ run_gunicorn -b

Think of the django project as the sandwich filling between the two slices of bread.


Supervisor is a process control system. Essentially is made up of two programs.

  1. Supervisord is the daemon. It can run any process you want, but in this setup we’re using it to run separate gunicorn processes for each django project.
  2. Supervisorctl is control program and monitor. This is used to start, stop, reload, show the status of the processes and perform other useful operations.

What’s really nice about using supervisor for handling gunicorn in this way is that you can start and stop individual projects. If client X needs to be restarted then client Y won’t get any 502 proxy errors.

Think of supervisor as the bottom slice of bread.

More To Follow

I’ll expand on these ideas with some actual examples including a really nice configuration for avoiding the dreaded 502 proxy error that can be encountered when starting and stoping gunicorn processes, but for now you might like to read more about the django filling.