Quantcast
Channel: Teach Me To Code » Ruby on Rails
Viewing all articles
Browse latest Browse all 34

Deployment with Capistrano

$
0
0

One problem that seems to face people when they’re attempting to move their applications into production is the best way to manage deployment of their application. This is where tools like capistrano comes in.

Capistrano was written by Jamis Buck of 37signals. In a lot of ways it has become the defacto way to deploy Ruby on Rails applications. It has also had tools like webistrano build on top of it to provide a graphical interface to the command line tool.

To get started, you need to install the capistrano gem:

gem install capistrano

Once you have the gem installed go to your application’s directory and capify the app.

cd /path/to/app
capify .

This will create two new files in your application’s folder: a Capfile in the application’s root folder and a deploy.rb in the application’s config folder. The deploy.rb file is where all of the magic happens. Here’s the default deploy.rb:

set :application, "set your application name here"
set :repository,  "set your repository location here"

set :scm, :subversion
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`

role :web, "your web-server here"                          # Your HTTP server, Apache/etc
role :app, "your app-server here"                          # This may be the same as your `Web` server
role :db,  "your primary db-server here", :primary => true # This is where Rails migrations will run
role :db,  "your slave db-server here"

# If you are using Passenger mod_rails uncomment this:
# if you're still using the script/reapear helper you will need
# these http://github.com/rails/irs_process_scripts

# namespace :deploy do
#   task :start {}
#   task :stop {}
#   task :restart, :roles => :app, :except => { :no_release => true } do
#     run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
#   end
# end

Let’s start at the top and work through this deployment recipe one line at a time.

First, set the application name to whatever you call your application. In my recipes, I set it to the url where you can access the application. This tells me where the application is deploying to.

set :application, "testapp.charlesmaxwood.com"

Now I need to tell the recipe where I store my code. I store mine at github, which obviously means I use git as my source control manager.

set :repository,  "git@github.com:charlesmaxwood/testapp.git"

set :scm, :git

One thing that drives me crazy with the default git setup is that it checks out your github repository, tars it up, copies it to your server via sftp, untars it, and then restarts your webserver. I’d much rather have my server just check the source code out from my github account. Lucky you and I, there’s an option to do that.

set :deploy_via, :remote_cache

This option just works for public repositories, but private repositories require authentication. Most git repositories use rsa public/private keys for this. Github has a guide for this.

Now that we can get the code, now we need to tell capistrano how to get onto the server we want our application deployed to.

set :user, "root"
set :use_sudo, false

We also need to define server roles. In my case, the database, app, and web servers are all the same server.

role :web, "#{application}"                          # Your HTTP server, Apache/etc
role :app, "#{application}"                          # This may be the same as your `Web` server
role :db,  "#{application}", :primary => true # This is where Rails migrations will run

Remember, application is the actual domain that I’m deploying to, which will resolve to the ip address of the server I want my application on.

By default capistrano will use sudo to deploy, which means you can use a user other than root. I use root and turn sudo off because most sudo configurations give the user sudo access to all commands by default. In this case, I don’t see much difference between that and just using root. This is primarily due to the fact that I don’t care to spend the time to make sudo more restrictive for my deployment user.

Now, let’s tell capistrano where to put the application on your server:

set :deploy_to, "/var/www/testapp"

The final thing we need to do is define any tasks we want capistrano to perform when it deploys. A few of these things may be installing gems, stopping/starting daemons, seeding data, or restarting your webserver.

The sample deploy stop and start tasks didn’t work for me out of the box. As soon as I uncommented them, it complained about the {} following each one. So, here’s what I changed them to:

namespace :deploy do
  task :start do
    run "/etc/init.d/apache2 start"
  end
  task :stop do
    run "/etc/init.d/apache2 stop"
  end
  task :restart, :roles => :app, :except => { :no_release => true } do
    run "touch #{File.join(current_path,'tmp','restart.txt')}"
  end
end

The restart task in this case works for me because I’m running Phusion Passenger for my rails applications. You can restart passenger for your application by modifying or touching the tmp/restart.txt file.

Another task I usually need as I develop my applications is to install all of the gems in the config/environment.rb file.

namespace :gems do
  task :install do
    run "cd #{deploy_to}/current && RAILS_ENV=production rake gems:install"
  end
end

Of course, having the task there doesn’t actually run it. You have to tell capistrano to run your task.

after :deploy, "gems:install"

You also need to run migrations. The task is built in, but I usually call it explicitly.

after "gems:install", "deploy:migrate"

Overall, I’ve been extremely impressed with Jamis’ work. I love what he’s provided for us to use in deploying our applications.


Viewing all articles
Browse latest Browse all 34

Trending Articles