over 8 years ago

The goal of this post is to summarize the steps needed to deploy a Django project running on nginx and gunicorn on Mac OSX. I am going to document a list of problems encountered and provide solutions below. (If you are running on Linux, I imagine the process will be very similar)

My setup (the installation order of the following packages matters, just keep on reading. But you don't have to have the exact same versions listed below):

 Python             2.7.9
 pip                6.0.6
 Virtualenv         12.0.4
 VirtualenvWrapper  4.3.1
 psycopg2           2.5.4
 Django             1.7.3
 gunicorn           19.1.1
 brew               0.9.5
 nginx              1.6.2

First thing first, install Python and pip. This should be the easiest part as the official website provides a installer. So I am not going to elaborate on this part.

Once Python and pip are installed, I recommend to install virtualenv and virtualenvwrapper next.

pip install virtualenv 
pip install virtualenvwrapper

Upon completion, let's create a virtual environment for our later setups:

cd ~                    <- cd to your user directory
mkdir .virtualenvs      <- create an empty folder called .virtualenvs
nano .bash_profile      <- open the .bash_profile file

Copy the following lines into your .bash_profile and save.

export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh

Once the file is saved, make sure to reload it:

. .bash_profile         <- Note the space between the two dots

Now we can create a virtual environment to install the rest by:

mkvirtualenv webapp

Now your bash prompt should have (webapp) in front of it, meaning you are currently in the 'webapp' environment.

Next, you should install the Postgres.app. The Postgres.app encapsulate PostgreSQL into a nice installer and makes the installation process extremely easy. Once completed, install psycopg2 (Note: you have to install Postgres.app first before installing psycopg2 otherwise you will (run into an error)[http://cheng.logdown.com/posts/2015/01/17/install-postgresql-and-psycopg2-on-mac-osx])

pip install psycopg2

Then, we can install Django and gunicorn:

pip install django
pip install gunicorn

In the end, we need to rely on brew to install nginx. To install brew, copy and paste this line into your terminal:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Once completed, install nginx:

brew install nginx

Summary of Installation

Let me explain how each aforementioned package fits within the big picture. To make everything easier to understand for novice users like myself, I simplified the functionalities of the pieces below, so please go to their websites for a more accurate description.

1. Virtualenv and Virtualenvwrapper
Virtualenv allows you to create a 'sandbox' that contains all of the Python packages you need for deployment without messing up the system's python environment. Virtualenvwrapper as its name suggests, wraps around virtualenv to provide a list of 'shortcut' commands to reduce the amount of efforts needed to create/switch between/delete virtual environments. The sole purpose of these two pieces is to isolate your deployment environment from other Python environments on the same machine.

To illustrate this issue with an example, I develop and deploy Django projects on the same machine for learning purpose. When I work on a Django project, I use the latest version of Django. But when I deploy it, I use an older version. Without virtualenv, I have to install the latest Django for development and delete it and install an older version for deployment. They can never co-exist at the same time. Virtualenv allows me to create two separate environments with different Django version in each and co-exist nicely.

2. Postgres.app and Psycopg2
The Postgres.app installs the PostgreSQL server on your machine with one click. It also provides a shortcut for you to open up a Terminal as a client that connects to the database server. Psycopg2 is used by Django or any Python program to access the PostgreSQL database programmatically.

3. nginx and gunicorn
Why do we need two servers instead of one?Well, by using gunicorn alone, it is enough to get your Django project up and running. The purpose of adding nginx in front of it is for:

  1. Load Balancing - The more servers you have the more users you can serve concurrently. But who should be the one that directs traffic to different servers? Well, the nginx server in this case. (I am aware that I have everything running on a single Mac...)
  2. Acceleration - Not all of the contents on your web page are dynamically generated. For instance, CSS style sheets, the logo of your website, javascript libraries like jQuery. We can have a server dedicated for serving these static contents so that our gunicorn server can focus on serving dynamic contents.
  3. Security - Users never see the gunicorn server. The only server exposed to the outside world is the nginx server. The gunicorn server will never accept traffics other than the ones forwarded by nginx.

Please read this link to learn more.

The choice of which server to use is arbitrary in this case. You can replace nginx with Apache and gunicorn with (uWSGI)[https://uwsgi-docs.readthedocs.org/en/latest/]. You should Google to find out more about them and see which one fits better with you.

This concludes the first part of this post. Here is the second part but I suggest you taking a break as the second portion is rather long.

← The Joy is in Creating, not Maintaining Deploy Django + nginx + gunicorn on Mac OSX (Part 2) →
comments powered by Disqus