Skip to content

Production Deployment

jrochkind edited this page Jan 11, 2012 · 16 revisions

Starting a rails app with rails server works fine for development and quick-and-dirty demo, but is not the way you'd want to do a production deployment or expose the app to the world.

We'll cover some basics of Rails 'environments', mention Passenger as one easy way to deploy a Rails app, and then discuss a few specific issues of Umlaut. Those already very familiar with Rails deployment may still want to check out the Umlaut section at the bottom.

Rails environments

Rails apps are set up to be run under a number of 'environments' -- by default, development, test, and production. See more at the Rails Getting Started Guide.

Databases

If you look in your ./config/database.yml, you'll see you (potentially) have a database defined for each environment. You'd generally want a different db for development and production, not share the same db.

When you ran rake db:migrate to create the Umlaut db schema, it by default ran under the development app environment. To create the app's schema in the configured production database, you set the RAILS_ENV env variable before running the command, like so:

RAILS_ENV=production rake db:migrate
  • If you have installed a new version of Umlaut with new schema changes, you can run this again.
  • But it may be tricky to do that in production with zero downtime, although it can be done with very minimal downtime. Run the migrations in the new version of the app, then immediately restart the app (see below under Passenger).

Config

As in all standard Rails apps, some environment-specific config can be found in ./config/environments/development.rb or ./config/environments/production.rb, respectively. You can look in there to see how standard Rails apps are configured differently in development vs production, and change settings if desired.

(You can create your own new environment, like 'staging', pretty much simply by creating a ./config/environments/staging.rb and referencing a db in ./config/database.yml).

In other places where you need to decide inline what to do based on environment, you can check the Rails.env variable, which will have a string in it. For instance, maybe in config in ./app/controllers/UmlautController. Not ideal, but it works.

Asset Pipeline

Rails 3.1+ plus apps by default use an Asset Pipeline (see Rails Guide) to compile/aggregate CSS and JS before delivery to the browser.

The asset pipeline compilation process requires a JS runtime -- the gem 'therubyracer' line in your Gemfile is one way to make one available to the app, if there wasn't a host-installed JS runtime findable by rails.

In development, for convenience, the asset pipeline compiles assets on demand, and doesn't actually aggregate them. However, in production, the default settings expect precompiled assets to be available, and will not compile them 'on demand' in a running app.

If you run rake assets:precompile in your app, it will compile assets to ./public/assets. You can run this in your app on the production server/location, or you can run it in another location and copy ./public/assets over to production location. (This way you wouldn't need a JS runtime at all on production server, as far as the asset pipeline is concerned).

Alternately, you can set config.assets.compile = true in your ./config/environments/production.rb to tell the app that, even in production, be willing to compile assets on demand if a precompiled assets is not present. I think this will be a performance hit only on first time an asset is requested (basically first request to a (re-)deployed app), and subsequent requests should be the same as if you had precompiled assets.

Some people use a tool call Capistrano for automating Rails app deployment process, including things like precompiling assets when you deploy. jrochkind has never gotten into capistrano, finding the learning curve not worth whatever time it would save him for his relatively simple deploy process. But some people swear by it for Rails apps.

Testing setup under production environment

Passenger

restart with touch ./tmp/restart.txt.

passenger-status

set number of instances started up.

Umlaut-Specific Concerns

number of instances

database connections

concurrency

service logging

nightly_maintenance

Clone this wiki locally