Matt Warren

Migrating from Apache to Nginx + Gunicorn

I was never really sure why people opted to swap out the heavily tested, widely deployed Apache web server for alternatives other than those trying to eek out a little bit more performance.  Finally I found a good reason to change my setup.

When trying to enable Celery for asynchronous tasks on my web server I ran into some unexpected errors with imports.  Eventually I tracked the problem down to mod_wsgi was compiled and running against an old version of Python rather than the newer version in the apps virtualenv.

The bigger problem with Apache outside of any performance issues is the coupling of Apache, mod_wsgi and python.  Upgrading python becomes complex and running multiple django apps on different versions of Python is non-trivial.  The other issue I found is that Apache takes several minutes to reload which is enough time to disrupt users.

Nginx acts as a trivial reverse proxy.  Once it’s configured and running it will probably never need to be restarted.  It directs incoming requests to a free standing python application that is running and listening at localhost:8000.  Gunicorn is used to run the django app on port 8000.  It can be run from the command-line all within the virtualenv’s copy of python and gunicorn.  This way the django app is nicely isolated and it operates without tying itself to too much of the OS.

Making the gunicorn process a daemon so that it runs in the background and starts after a system reboot is handled by having Supervisor running.

The real day to day benefits to getting rid of Apache is that deployments are faster and there’s less downtime when restarting the server.  It also gives more flexibility for upgrading python rather than using the system installed version.  In the end it was easier to switch to Nginx + Gunicorn + Supervisor rather than fixing the Apache config to work with Python 2.7.3


Posted

in

by

Tags: