views:

785

answers:

3

What are some best practices and general theory of multi-stage deployment for web apps?

I'm particularly interested in deploying Rails apps using Git, Capistrano, and Passenger, and I've found posts that discuss the nuts and bolts of the process:

What considerations should I take with regard to each stage (testing, staging, production)? Should the stages be deployed to different physical servers? Any tips or advice about multi-stage deployment? Any snags I should look out for?

best,

Jacob

A: 

It is better to have two different server environments: staging and production. I always ignore the test environment. The test environment acts like production, but rolls back the database when done. Running both on the same server may negatively affect the performance and stability of the production environment. Upgrading a gem to test in the staging environment may affect production negatively and cost you downtime.

You must be very vigilant that the same gem versions are on both servers. It can spell trouble if a version of an app works in staging but doesn't in production because of this sort of discrepancy.

I would always have a console window open that is ready to roll back the last deployment in case something goes wrong. There really isn't much more to the process than that.

Save yourself some money and buy the cheapest staging server you can. You're the only one that will be using it, right? Just make sure they are from the same provider.

The test environment isn't an environment in which you should run a server. It is strictly intended for use by your unit, functional and integration tests. Most people "run" this on their same development box, since if you should be running your tests prior to checking in any new code.
Steve Madsen
+1  A: 

I've always just created cap tasks for each deploy target and used them on the command line:

# deploy.rb
task :stage do
  server 10.0.0.1 ...
end

> cap stage deploy

You can also define customize tasks inside each target task, such as a deploy that does cleanup in staging, but doesn't in production.

Since these deploy target tasks are rarely very big, I never really saw the point of something like installing the cap extensions for multi-stage, but I suppose other's situations may be different.

I do think production should be separate from your other environments, otherwise there's a danger that misbehaving processes in staging or the like could affect production performance.

Sometimes I define cap tasks for convenience in staging, such as blasting out the database and reloading it from the most recent production dump. These tasks should check their deploy target via a set variable or the like and refuse to run for production as insurance against a late night typo.

It's tempting to put lots of custom behavior in your deploy.rb, but I've found this tends to bite back and require a lot of maintenance effort as your environment or the cap api's change.

Another practice I've seen with larger environments is to have a shell account with a checkout that tracks the stable branch specifically set up to act as the capistrano control point. You ssh in and run cap commands there instead of locally. This can help avoid issues where your local checkout's deploy.rb has modifications that you aren't ready to use with deploying to production. This is less of an issue with git vs svn, but still one must be careful to think about what their local deploy.rb is at the moment they're running cap commands.

Heroku is really making this stuff easy these days, and EY and others aren't exactly far behind.

Jason Watkins
A: 

We have been using the capistrano multistage deployment very successfully for over a year. The system nicely separates the deployment files for each stage in an almost identical way to the Rails environment files. It was very easy to setup and manage.

Peer Allan