March 25th, 2008 admin
Building your app in rails is just the first step. After that comes the grueling task of deploying it. I used to simply copy my project over to my web directory, start my mongrels and leave it at that. If I was thoughtful, I would create a backup of the previous installation, but since it was all tested locally, I would never need that right? 
Naturally projects grow, and deployments become more complex. Copying a folder over on a single server may not be that bad, but once you start talking about multiple servers, folks start running for the exits. On top of that, this manual approach usually costs a good bit of downtime, which has to be scheduled, and I don’t know about you, but once i have typed the same sequence of commands a few times, I am looking to write a script!
Don’t bother with the scripts! Let Capistrano handle all that hordazzlement. We recently had a demonstration from the Mor.ph guys, and they were showing us how simple it would be to deploy a rails application to one of their ultra nifty free dev shards. The first thing stated was “Deployment is simple! just point your cap file to…”. You can imagine the rest. So the point of that is that capistrano is pretty much the defacto deployment vehicle in the rails community these days.
What is Capistrano
The guys who wrote rails also brought you capistrano, and like rails they were solving some very specific problems. Specifically , they needed a tool that would do the following:
- Secure update of multiple database servers and websites from a centralized source repository
- A rollback mechanism that would allow you to undo what you perpetrated if necessary
- reduce downtime during migration
- integrate with Rails
- handle the restarting and configuration of production environment
If you are like me, you do not have your database.yml file checked into source. In fact you have subversion ignoring it entirely. The reason for this is that each developer tends to have their own database.yml, and you don’t want their check-ins to break anyone elses environment. In order to have capistrano deploy my application without a database.yml file to production, I would need capistrano to copy the production database.yml file over into the newly created directory. Furthermore, I did not want the production database connectivity to be in subversion at all, preferring instead to create an external configuration file on the production servers. It turned out that moving such a file with capistrano s a trivial thing to do .
Getting Started
First things first, get the capistrano gem on the machine you will use to initiate deployments.
sudo gem install capistrano
Capistrano does not need to run on the target machine, you only need to have it on your deployment client. This is because Capistrano uses SSH and SFTP to do all its work.
The next thing you need to do is develop a deployment file. cd into your rails application and type
skiptree.com$ capify .
[add] writing ‘./Capfile’
[add] writing ‘./config/deploy.rb’
[done] capified!
This will set you up with two essential files, one of which (deploy.rb) We will modify for our target environment. The default deploy.rb looks like this:
set :application, “set your application name here”
set :repository, “set your repository location here”
# If you aren’t deploying to /u/apps/#{application} on the target
# servers (which is the default), you can specify the actual location
# via the :deploy_to variable:
# set :deploy_to, “/var/www/#{application}”
# If you aren’t using Subversion to manage your source code, specify
# your SCM below:
# set :scm, :subversion
role :app, “your app-server here”
role :web, “your web-server here”
role :db, “your db-server here”, :primary => true
The basics are fairly straighforward. Simply provide your connectivity information.
set :application, “skiptree.com”
set :repository, “svn+ssh://my.secret.source/opt/trunk”
set :deploy_to, “/var/www/#{application}”
role :app, “skiptree.com”
role :web, “skiptree.com”
role :db, “skiptree.com”, :primary => true
# forces a checkout from source and copies to remote
set :deploy_via, :copy
task :after_update_code do
run “ln -nfs #{deploy_to}/#{shared_dir}/config/database.yml #{release_path}/config/database.yml”
end
The only thing new here is the task :after_update_code. In that task i simply create a command to run on the target server which executes after the code is updated. The {release_path} variable resolves to a “shared” subdirectory. i.e. /var/www/#{application}/shared. or “/var/www/skiptree.com/shared” on the target host. I simply placed my production database.yml into the config subdirectory and called it a day.
now all that i need to do to trigger your first deployment is type:
> cap deploy:cold
The cap commands are all available via “cap -T”, after you have done your initial cold deploy, you can simply tyle “cap deploy” for subsequent release. if you dont like what happened… “cap deploy:rollback”! Have fun!…
Posted in Rails | 2 Comments »