cap production deploy

May 7th, 2007

This is a great little tip if you use Capistrano 2.0 to deploy to multiple servers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
task :production do
  role :web, "web.example.com"
  role :app, "app.example.com"
  role :db,  "db.example.com", :primary => true
  
  set :deploy_via, :remote_cache
  
  set :start_mongrel,   "/path/to/mongrel_cluster start"
  set :stop_mongrel,    "/path/to/mongrel_cluster stop"
  set :restart_mongrel, "/path/to/mongrel_cluster restart"
end

task :staging do
  role :web, "staging.example.com"
  role :app, "staging.example.com"
  role :db,  "staging.example.com", :primary => true
  
  set :deploy_via, :checkout
  set :mongrel_rails, "/path/to/mongrel_rails"

  set :start_mongrel, "#{mongrel_rails} start -d 
                       -p #{application_port} 
                       -e production 
                       -P #{current_path}/log/mongrel.pid 
                       -l #{current_path}/log/mongrel.log 
                       -c #{current_path}"
  set :stop_mongrel, "#{mongrel_rails} stop 
                       -P #{current_path}/log/mongrel.pid"
  set :restart_mongrel, "#{mongrel_rails} restart 
                       -P #{current_path}/log/mongrel.pid"
end

namespace :deploy do
  
  desc "Restart mongrel"
  task :restart, :roles => :app do
    sudo restart_mongrel
  end
  
  desc "Start mongrel"
  task :start, :roles => :app do
    sudo start_mongrel
  end
  
  desc "Stop mongrel"
  task :stop, :roles => :app do
    sudo stop_mongrel
  end
  
end

Capistrano 2.0 gives you powerful new options using namespaces and tasks. As you can see, we set up special tasks for staging production, and then set our variables for each environment there.

If you’re familiar with Capistrano deploy.rb file, then the role lines should be pretty self-explanitory. We just set up different roles for the staging environment and the staging environment.

Now, on my particular setup, I use mongrel_cluster in production, but plain old Mongrel in staging, just to keep things simple. In order to accommodate the two different commands, I just assign the command to appropriate variables inside the :staging and :production tasks, and then call the variables from sudo.

Now you can do things in your different environments by calling

1
2
3
4
cap production deploy          # Deploy to production
cap staging deploy             # Deploy to staging
cap production deploy:restart  # Restart mongrels on production
cap staging deploy:update_code # Update code

You’ll also notice that I used a different deploy_via in each environment. In production, I want to deploy_via :remote_cache because it is much quicker than a full svn export. But on my staging server, I want to be able to cheat and run svn update occasionally so that I don’t always have to do a full deploy.

Theoretically, you could have any number of different environments, and any combination of different variables for each environment. Really though, the simpler the better – with a staging server, the point is to get as close as possible to emulating the actual environment of the production server. For those little variations, this setup works great.