This tutorial is aimed at beginners and is a part of a series where we learn to run a django app with Gunicorn and Nginx, and manage it with the help of the Supervisord. Basically, we are trying to emulate a production environment.
The Problem
We are all very well aware that we can run our django app simply by executing a ./manage.py runserver
command. We also know that it is called a development server for a reason. You know it is not robust, security issues, thread issues and etc. So, how do we really run our app then?
The Solution
Enter Gunicorn, a simple, light and speedy Python WSGI HTTP Server for UNIX. We will see how to use gunicorn now but it is not the main reason I wrote this tutorial. The main reason is this: back in the day I was terrified at the thought of anything related to production vs development stuff because I thought, you know, THESE ARE NGINX and GUNICORN which can support millions of requests per second and are very secure/robust/reliable and thus should be very difficult to learn and configure. I want to prevent others from experiencing the same and demonstrate that it is really simple and simple.
Enough talk, let's fight! (YAY, always wanted to quote Kung Fu Panda)
Installation
First, let's go ahead and update/upgrade our packages:
sudo apt-get update
sudo apt-get upgrade
Now, install pip
. If you are using python2, type the following:
sudo apt-get install python-pip
If you are instead using python3, type the following:
sudo apt-get install python3-pip
Now install virtualenv
: For python2:
sudo pip install virtualenv
For python3:
sudo pip3 install virtualenv
Let's go ahead now and install a virtual environment at /opt/envs/myprojenv
. You can install it anywhere you like and in real life use a more descriptive name for the virtualenv:
virtualenv /opt/envs/myprojenv
Activate it:
source /opt/envs/myprojenv/bin/activate
You should now see (myprojenv)
at the beginning of your command line.
Now, install Django. By the way, we will only use pip
from now on, not pip3
, as we are inside a virtual environment:
pip install django
Create a project:
django-admin startproject myproject
Apply migrations and run the development server:
cd myproject
./manage.py migrate
./manage.py runserver
Go to localhost:8000/admin
and make sure that it is running. Is it running? Cool! Easy right?! Now we will replace this development server with gunicorn and you will see that it is as easy.
Install gunicorn:
pip install gunicorn
Run this, go to localhost:8000
and behold the magic:
gunicorn myproject.wsgi
DO YOU SEE IT? It is this easy.
Now you might be wondering what is that wsgi
thing is. Well, it stands for Web Server Gateway Interface and basically is a way how apps/frameworks and servers talk to each other. If the server(like Gunicorn) has wsgi
implemented and so has your framework(Django), it means that you can run your app with that server. And the entry point of communication for these two is the variable application
, which is located in myproject/wsgi.py
in our case. You can read more about this in PEP 333.
Let's play with it a little bit to see what it got.
We can bind it to a specific port:
gunicorn --bind 0.0.0.0:8030 myproject.wsgi
You can increase the number of workers to serve requests, which you probable will in real life as your users increase:
gunicorn --workers 3 myproject.wsgi
Run it in a daemon mode:
gunicorn --daemon myproject.wsgi
Or all of them altogether(a shorter version):
gunicorn -d -b 0.0.0.0:8030 -w 3 myproject.wsgi
Read more about these options in the docs
If these options get too long, you can create an ini
file and run it like this:
gunicorn -c /path/to/config/file myproject.wsgi
After running your app with gunicorn, go to the django admin panel at localhost:8000/admin
. You will see that all styles are gone. The reason is that gunicorn is an application server and it does not serve static files. In order to solve this problem, we will take a look at Nginx
next and use it as a reverse proxy for gunicorn. We will talk about what reverse proxy
is as well so don't think about it for now.
Well, that's it for now. This is a brief overview of django with gunicorn. Go to docs and read more.
Fight on!