Zend Framework deployment with Capistrano

After playing around with Phing for a while I decided to bring the simplicity of Capistrano – which I have been using with my Rails apps – to our Zend Framework project at work. Surprisingly it wasn’t hard at all.
“Capistrano is a tool for automating tasks on one or more remote servers”. That’s straight off their website and this tool rocks.

Capistrano is written in Ruby and needs the ruby library to be installed on the client machine. It does not need ruby on the production or any other target servers and at work we deploy from two machines and needed ruby installed on just the two. However the ruby files for the deployment recipes need to be in source control along with the rest of the code.
The following resources came in useful while we were setting up:

I use Ubuntu at work and the following steps are what we had to do to get Capistrano working on Ubuntu 8.04 but should work on most distros.

Step 1: Installing Ruby and Ruby gems

Install ruby packages

sudo aptitude install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8 libreadline-ruby1.8 libruby1.8 libopenssl-ruby

Create some symlinks from the ruby install to their locations

sudo ln -s /usr/bin/ruby1.8 /usr/bin/ruby
sudo ln -s /usr/bin/ri1.8 /usr/bin/ri
sudo ln -s /usr/bin/rdoc1.8 /usr/bin/rdoc
sudo ln -s /usr/bin/irb1.8 /usr/bin/irb

Make sure subversion is installed

svn --version

If not installed, install it. You could of course use another source control system. Git seems to be the new hotness.

sudo apt-get install subversion

Install rubygems from source

mkdir ~/sources
cd ~/sources
w get http://rubyforge.org/frs/download.php/56227/rubygems-1.3.3.tgz
tar xzvf rubygems-1.3.3.tgz
cd rubygems-1.3.3
sudo ruby setup.rb

Create a symlink for rubygems and update it

sudo ln -s /usr/bin/gem1.8 /usr/bin/gem
sudo gem update
sudo gem update --system

Install capistrano, capistrano multi-stage and echoe gems

sudo gem install capistrano
sudo gem install capistrano-ext
sudo gem install echoe

That’s it. The Ruby environment is all set up.

Step 2: Creating the deploy file

Change to the root directory of your application, create a ‘config’ folder if you dont have one and type

capify .

Capistrano creates two files. A ‘Capfile’ for loading the deploy script and the deploy script itself. Open up the Capfile and remove the line where it tries to load plugins. This is specific to the Rails framework.
The Capfile should now look like this:

load 'deploy' if respond_to?(:namespace)
load 'config/deploy'

Open up the deploy.rb file created in the config folder and edit it for your setup.
The various configuration parameters are available on the Webistrano website. Our sample recipe is further down the page.

Step 3: Add multistage

For deploying to multiple environments, the capistrano multistage extension needs to be added. We usually have a staging, integration and a production stage and I’ll assume that here.
For multi-stage, the capistrano-ext gem needs to be included, the various stages specified and the default stage set. Furthermore, all configuration parameters not common to all stages need to be taken out of the deploy .rb file.

Create a deploy folder in the config directory and add a file for each of your environment. In our case we have production.rb, integration.rb and staging.rb files.
Add the environment specific parameters to these files.
Our sample deploy.rb file looks like:

set :stages, %w(staging integration production)
set :default_stage, "staging"
require 'capistrano/ext/multistage'

set :application, "app"

#############################################################
#	Settings
#############################################################

default_run_options[:pty] = true
set :use_sudo, false

#############################################################
#	Servers
#############################################################

set :user, "username"
set :domain, "example.com"
set :port, 22
server domain, :app, :web
role :db, domain, :primary => true

#############################################################
#	Subversion
#############################################################

set :repository,  "http://example.com/svn/#{application}/trunk"
set :scm_username, "svn-user"
set :scm_password, "svn-pass"
set :deploy_via, :export

#############################################################
#	Tasks
#############################################################

after :deploy, 'deploy:cleanup'

# overide Rails specific tasks here.

desc "Do nothing"
deploy.task :restart, :roles => :app do
    # do nothing. php deploys don't need a server restart
end

deploy.task :migrate, :roles => :app do
    # migrate task is rails specific
end

Our staging deploy file sample (APPROOT/config/deploy/staging.rb)

set :deploy_to, "/path/to/staging"

If your staging and production environments are on different servers you obviously need to move the ‘Servers’ section to the individual deploy files.

Step 4: Setup and do initial deploy

The first step is to setup the server for Capistrano. Capistrano has a command to do this but due to the way it works, the application will be deployed to a folder called ‘current’ (really just a symlink to the latest release) within your ‘deploy_to’ directory. This means the document root (for apache virtualhost) will be in /path/to/staging/current/public rather than /path/to/staging/public and your apache (or nginx, etc.) config has to be changed to reflect this.

Commit the files to subversion (insert your SCM here) then type:

cap deploy:setup

This command creates two directories in your deploy_to path, releases and shared. The releases directory stores versions of the application as they are deployed. The”after :deploy, ‘deploy:cleanup’” line in the recipe cleans up this folder by keeping just the latest 5 (by default) releases. The ‘shared’ folder is for storing images and other files that are not part of your application and are therefore not under source control.

To deploy your app, run:

cap deploy

This deploys to the default stage – staging in our case.
To deploy to production you’d type:

cap deploy production

It’s as easy as that. This is obviously not specific to the Zend Framework and can be used with any app.

Related posts:

  1. Giving up on mongrel_cluster on windows
  2. Jara Base – a base Zend Framework app
This entry was posted in Zend Framework. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>