Django & Capistrano

One of the major Django‘s drawback for a project like Paperblog is the lack of automated deployement tools, like what Capistrano is for Rails. But Capistrano is designed to be flexible, this is how to get it able to deploy Django project.

Installation

The best way to install Capistrano is to use rubygems :

sudo apt-get install rubygems ruby ruby-dev sudo gem install capistrano fastthread thermios

Recipe

Before going a step further, this is basically how Capistrano works. Capistrano is watching for a file named Capfile in the root directory of your project.
This file contains all the recipes of your deploy, each recipes is composed of simple task that you can regroup, execute only on a certain kind of machine, render atomic, etc. For example :

namespace :deploy do desc "Restarts your application" task :restart do sudo "/etc/init.d/apache2 reload" end end

Capistrano offers us already written tasks to deploy application from a subversion repository on n servers with distincts roles (app, web, db, etc.).
Some of them suppose that your are deploying Rails applications, so we only have to redefine them in order to make Capistrano able to deploy our sweet Django project.

Capify

To capify our Django project, we just need to create a Capfile file in the root directory of our project and add this line in order to import all predefined Capistrano tasks :

load 'deploy' if respond_to?(:namespace)

Before going further, take a look at the Capistrano’s predefined tasks documentation.

First of all, we need to declare some essential variables like : the subversion repository’s url, the name of our project, define role for each server, etc. Most of them are already documented, once again, take a look at the Rails documentation.

#REQUIRED VARIABLES set :application, "myapp" set :repository, "http://dev.example.com/myapp/trunk" #ROLES role :app, "production.example.com" role :web, "production.example.com" role :db, "production.example.com", :primary => true #OPTIONAL VARIABLES set :keep_releases, 3 set :deploy_to, "/var/www/myapp/" set :group_writable, true

We finally just need to redefine task in order to feed our needs and our project. Let’s start by the obvious, task for start and restart :

namespace :deploy do desc "Restarts your application" task :restart, :roles => :app, :except => { :no_release => true } do sudo "/etc/init.d/apache2 reload" end desc "Start the application servers" task :start, :roles => :app do sudo "/etc/init.d/apache2 start" end end

And then we need to adapt these rules for Django, don’t be afraid to change things to reflect your very own project or to add other task :

namespace :deploy do after 'deploy:symlink', 'deploy:files' desc "Install settings and media files" task :files, :roles => :app, :except => { :no_release => true } do run "ln -nfs #{shared_path}/system/settings.py #{release_path}/settings.py" run "ln -nfs #{shared_path}/media/ #{release_path}/media" run "ln -nfs #{shared_path}/cache/ #{release_path}/cache" end desc "[internal] Touches up the released code" task :finalize_update, :except => { :no_release => true } do run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true) end desc "Prepares one or more servers for deployment" task :setup, :except => { :no_release => true } do dirs = [deploy_to, releases_path, shared_path] dirs += %w(system media cache).map { |d| File.join(shared_path, d) } run "umask 02 && mkdir -p #{dirs.join(' ')}" end desc "Deploys and starts a `cold' application" task :cold do update start end end

These tasks create 3 directory that will be keep between each deploy :

The directory ”/var/www/myapp/shared/” will contains every file that are independant from your code or specific to your server. And each file will be linked to the current deployed version via a symlink.
The directory ”/var/ww/myapp/current/” is pointing to the latest ”release” of your project.

You are ready to deploy your Django project using Capistrano :

cap deploy

To make your life easier, this is a Capfile ready to server with some extras inside !

Download the Capfile example.