Five Days to a Django Web App: Day Four, Deployment

Thanks for your patience, and for coming back for a discussion of deploying our Django web app.

In case you missed any of the previous posts in this series, here they are:

  1. Day One, Get Ready (Concept and prep)
  2. Day Two, Mockups (Creating a design)
  3. Day Three, Coding (Coding tests, views, templates, and models)


First, we need to make a couple of decisions:

  • How are we going to push updates to the live site: FTP, git, svn?
  • How are we going to handle backups?

Version Control as Distribution System

In my case, I'm using svn+ssh to push updates. Notice that this does not require special setup on your server -- you do not need to install the svn stuff that DreamHost or your host may provide. Just do svn init to create a repository on the server (outside the DocumentRoot!). Then point your development pc to svn+ssh:// (Git works similarly, no support from your host required except the binaries.)

In the directory on the host where you're going to store your project files, point to the same URL. (You could use the file:///.../ url, but I prefer to avoid accessing the repo directly. Superstition?)

Now, whenever you make a change on your development system, just "svn ci" and then on the host "svn up" and restart your fcgi to pick up the new code. Presto! The live site is updated with your change.


You must have a backup strategy: Your app will have users. Your host's disk will burp. Your users will hate you when the disk burps and you don't have a good backup.

There are probably 374 different ways of backing up your Django app. The two major things you need to capture are the database and your code. If you are storing objects (e.g. uploaded files) outside the database, you'll need to back these up too. The option I'm using is django-backup.

Pull the code from subversion into your project. Rename the directory to "django_backup". Add django_backup to your INSTALLED_APPS. Verify it works by running ./ backup -c. Sanity check the backup by doing zless backups/*.gz. We'll set up a cron job on the host to run this regularly when we deploy.


I've previously written about deploying Django apps on DreamHost, so I'm not going to duplicate that here. Keep in mind that you want to use the version control strategy outlined above. Read that article, deploy your app and come back here when you're done.



Let's add that cron job we previously mentioned. On the host, run crontab -e. If you're on DreamHost and this if the first time you've used cron, it will prompt you for an email address to send output to. Then it will dump you into an editor. (Side note: "joe" is the default. If you want something different, like vim, be sure that EDITOR=/usr/bin/vim is set in your environment.)

Set up a job something similar to the following:

MAILTO=""# m h dom mon dow command 4 2 * * * (cd /home/PATH/TO/PROJECT; ./ backup -c

This will run a backup every day at 02:04 (AM). You will get two emails: one with the output from the job, and one with the compressed backup file. (When you get to the point where your database backups are too big for email, you'll need to find another strategy.)

Now we've got another problem to solve: we're going to accumulate a bunch of backups on the disk. Let's get rid of the old backups. This is pretty safe, since we're receiving backup files via email. Add a cron job like this:

14 2 * * * (cd /home/PATH/TO/PROJECT; touch --date=`date --iso --date='10 days ago'` .backup.oldest; find ./backups/ -mindepth 1 \! -newer .backup.oldest -execdir rm '{}' +)

(Formatted here for readability — you need to put that all on one line.)

This will remove backup files older than 10 days. You could do this more concisely with a tool like tmpwatch or tmpreaper, but neither is installed on my host and this incantation should work on pretty much any flavor and installation of linux.

At this point we're deployed and the majority of the work is done. Tomorrow we'll take a look at some maintenance issues.

Posted on 2009-03-02 by brian in django .
Comments on this post are closed. If you have something to share, please send me email.