TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Ask HN: Django Deploy Recommendations

109 pointsby juanefrenover 14 years ago
I have an app that uses Django Python and Postgresql.<p>Right now is running under Linux/Apache/mod_wsgi, how ever have read about Nginx and Gunicorn (also uwsgi and others) as a better option...<p>I would like to read your recommendations (advantages and disadvantages) about deploying django.<p>PS: I am mainly developer so I lack a lot of knowledge about sysadmin.

15 comments

ericfloover 14 years ago
I recommend nginx in front of gunicorn. This way nginx can sit up front and do what it does best: serve static media files and buffer requests and responses.<p>Set up gunicorn under some kind of process manager. I use daemontools, but runit, upstart, monit, and others can work very well too.<p>For updating code on the server, I'm a big fan of keeping it simple, and to me that means writing a small shell script that ssh's into your machine and runs the proper commands to update the code and send a HUP signal to gunicorn.<p>You can even set up this script as a git post-commit hook, so that every time you push, your code is updated. If you have a robust test suite, you can set up a Hudson instance to run this command when all tests pass.<p>If you plan to have long-lived connections (comet, many requests out to third party services), then make sure you set up gunicorn to use Eventlet workers. What that will do is transform your code into asynchronous evented code using coroutines. But you most likely won't have to worry about that.
评论 #1825734 未加载
评论 #1824835 未加载
评论 #1827018 未加载
评论 #1824919 未加载
coderholicover 14 years ago
Another great tool that hasn't been mentioned yet is Fabric. Combined with a VCS it makes pushing changes to the server an absolute breeze. With the simple fabfile shown below I only need to do "fab update" to push all of the latest code to the server:<p><pre><code> #!/usr/bin/env python from fabric.api import * env.hosts = ['example.com'] def update(): local("./manage.py validate") local("./manage.py test core") with cd("/var/www/example"): sudo("git pull origin master", user="www-data") sudo("./manage.py migrate --all", user="www-data") sudo("touch apache/django.wsgi", user="www-data")</code></pre>
Daishimanover 14 years ago
Here's what I've found that helps tremendously:<p>-Keep your software in a DVCS of some sort. I find Git and Mercurial to be great.<p>-Use virtualenv to abstract away from your current environment's Python distribution. Start clean and download the packages you need.<p>-Create a requirements file listing the packages that you need for you program. Put it in the same format that the 'pip freeze' command outputs, so that installing a new environment is quick and easy.<p>-Set up a local configuration file (not managed by version control) and a base configuration file with all the settings that are immutable. Import the local config file within settings.py so as to avoid local setting conflicts.<p>-In production, set up an nginx frontend to serve static files, and route all the Django urls to an Apache backend (or Tornado, or whichever App server you may want to use).<p>-I haven't tried anything else, but WSGI is super intuitive and easy to use.<p>-If you need it, try using Django-South for versioning database schemas. Do take into account that it has a bit of a learning curve.<p>-You don't need to put your python files in /var/www, any directory will do.
评论 #1824289 未加载
评论 #1824590 未加载
JshWrightover 14 years ago
I run nginx as a static file server and reverse proxy to uwsgi (via a local socket). I find the setup to be simpler than Apache/mod_wsgi, though both approaches meet my performance needs without any trouble. I run PostgreSQL as my database. (This is on a reasonably low traffic, but fairly data heavy site. It all runs comfortable on a Linode 512)<p>I'll just reiterate what Daishiman said regarding DVCS (like git or mercurial), virtualenv, and South. Use them! All three will make your life much easier 6 months from now.
endlessvoid94over 14 years ago
<a href="http://www.djangy.com" rel="nofollow">http://www.djangy.com</a> - in private beta, by wednesday we're hoping to invite several hundred more users.<p>if you're in a time crunch, email me (dave@djangy.com)<p>EDIT: email
评论 #1824321 未加载
评论 #1824380 未加载
tdavisover 14 years ago
nginx in front of gunicorn is fast, simple, efficient with resources, and reasonably scalable. Today, there's nothing else I would recommend.<p>Of course, use [d]vcs, setup.py, virtualenv, pip, and south (and a reasonable test suite!). Using these along with gunicorn as mentioned above has streamlined my deployment to a "one-click" process that leverages all of these packages to create an isolated, repeatable, rock-solid [re-]deployment with nothing more than a generic Makefile.<p>I've been doing Django development and deployment for over four years now and it is the closest thing to a "silver bullet" I've found.
room606over 14 years ago
I was in the same boat a few months ago and found this PyCon workshop by Jacob Kaplan-Moss extremely helpful<p><a href="http://blip.tv/file/3632436" rel="nofollow">http://blip.tv/file/3632436</a><p><a href="http://github.com/jacobian/django-deployment-workshop" rel="nofollow">http://github.com/jacobian/django-deployment-workshop</a>
IgorPartolaover 14 years ago
I usually deploy it is nginx =&#62; Django FastCGI via flup. Make sure to use prefork instead of threaded method. On top of that I run each Django project inside individual virtualenv's [1], where virtualenvwrapper [2] simplifies the process. Since all my servers are Debian-based, I use my own creation called flint [3] to automatically start/stop the FastCGI processes on boot/shutdown. For deploying code I use fabric [4] and then simply $ flint restart_all or $ flint restart myproject to reload the code.<p>[1] virtualenv - <a href="http://virtualenv.openplans.org/" rel="nofollow">http://virtualenv.openplans.org/</a><p>[2] virtualenvwrapper - <a href="http://www.doughellmann.com/projects/virtualenvwrapper/" rel="nofollow">http://www.doughellmann.com/projects/virtualenvwrapper/</a><p>[3] flint - <a href="http://igorpartola.com/projects/flint" rel="nofollow">http://igorpartola.com/projects/flint</a><p>[4] fabric - <a href="http://docs.fabfile.org/0.9.2/" rel="nofollow">http://docs.fabfile.org/0.9.2/</a>
metamemeticsover 14 years ago
<a href="http://jacobian.org/writing/django-apps-with-buildout/" rel="nofollow">http://jacobian.org/writing/django-apps-with-buildout/</a><p>Buildout. Like virtualenv but handles downloading correct required package versions too. gives you an isolated shell and django manager in your project directory. You can then distribute your project to different people and servers and ensure the correct version of python, django, etc. is used.
评论 #1824428 未加载
ianbover 14 years ago
Maybe try <a href="http://cloudsilverlining.org" rel="nofollow">http://cloudsilverlining.org</a> (<a href="http://cloudsilverlining.org/django-quickstart.html" rel="nofollow">http://cloudsilverlining.org/django-quickstart.html</a>)<p>Anyway, Apache/mod_wsgi is perfectly fine and I wouldn't bother tweaking out that part unless you have an issue with it.<p>I'd strongly recommend using a cloud provider so you can test your deployment process. You can do it without a cloud provider, but you probably won't because it won't be trivially easy to create new servers.
nwmcsweenover 14 years ago
Use varnish in front of apache. Why not nginx, lighttpd? Because apache has market share - there's modules for nearly everything. Going farther off the beaten path will just turn into a headache as you'll eventually want/need functionality offered by a application with a larger market share.
endtimeover 14 years ago
We're running nginx proxying to Apache/mod_wsgi on RHEL. I've heard from the Parsely guys that they got their memory usage waaaay down by skipping Apache and just using the nginx equivalent of mod_python - I seem to remember that they weren't sure how well it would scale, though.
rcoderover 14 years ago
Most of the recommendations here are good. Par for the course in Django deployments and administration is virtualenv, Fabric, pip, and per-server settings files.<p>On top of those, we use Apache, mod_wsgi, Fabric (in a slightly-weird way which I'll get into below), mod_xsendfile, Mercurial, and a home-grown migration library.<p>Serving static files via nginx or Apache is fine, but generally requires that you copy them out of your various pluggable apps and into some static docroot on every deploy. We use mod_xsendfile instead (with another Django helper app, which I'm hoping to get onto Bitbucket in the next week or two) to directly serve static assets out of the 'media' directory of each installed Django app.<p>Our use of Fabric is slightly non-standard, too, as I mentioned; instead of writing a single 'fabfile', we have a collection of development, testing, and deployment commands which use Fabric as a very high-level Python API for distributed command execution.<p>Regardless of the stack you choose, as a non-sysadmin, there are a few habits and practices I'd strongly recommend you keep in mind to avoid getting yourself into a painful place later:<p>First, set up a staging environment that looks as much like your production setup as possible. It can be on the same server, or in a local virtual machine, or (even better) on a spare server that can be pressed into duty if the primary ever goes down.<p>You should always have a recent dump of your production database loaded into this environment, and the ability to pull a more up-to-date snapshot in quickly. (This will help with recovering from major "whoopsies" in production, too, and force you to continually test your backups.)<p>Second, keep copious, detailed notes on <i>everything</i> you do while deploying, updating, or troubleshooting production issues. I'm literally talking about stuff like this:<p><pre><code> Created uploads directory: mkdir /var/www/uploads chown www /var/www/uploads chmod -x /var/www/uploads Configured upload directory in Django settings: echo "UPLOAD_FILE_DIRECTORY = /var/www/uploads" &#62;&#62; /usr/local/deploy/myapp/src/myapp/settings.py </code></pre> Some sysadmins I've worked with literally copy their entire .bash_history file for each session into a running log, though I find that tends to end up with a lot of noise ('cd ..; cd ..; pwd; ls; etc.') that doesn't help when you're trying to triage an issue.<p>I like to use simple text files (backed up in Dropbox, of course) for these notes, but a wiki is fine if that's your preference. It may seem like pointless duplication of effort at first, but grepping a directory full of notes to see what you changed is a much more reliable triage technique than counting on yourself to remember a bunch of details. This goes double when you're panicking in the middle of a production outage.<p>Beyond that, everything else is gravy. If you're using Apache/mod_wsgi now, I'd recommend you keep using it until you hit a real scaling limit, or have spare cycles to try out a secondary hosting setup post-launch.<p>(In case anyone's interested in that migration tool, it's on Bitbucket: <a href="https://bitbucket.org/rcoder/finch/overview" rel="nofollow">https://bitbucket.org/rcoder/finch/overview</a> )
sligover 14 years ago
You really should use nginx to serve static files and route everything else to apache. The setup is dead simple.
评论 #1824577 未加载
评论 #1824270 未加载
codydjangoover 14 years ago
use apache mod wsgi for django and nginx as a reverse proxy for serving static content.<p>this way you get the apache you know and love as well as a minimal memory footprint.