Zero downtime deploys with unicorn + nginx + runit + rvm + chef
Below are the actual files we use in one of our latest production applications at Agora Games to achieve zero downtime deploys with unicorn. You've probably already read the GitHub blog post on Unicorn and would like to try zero downtime deploys for your application. I hope these files and notes help. I am happy to update these files or these notes if there are comments/questions. YMMV (of course).
Other application notes:
- Our application uses MongoDB, so we don't have database migrations to worry about as with MySQL or postgresql. That does not mean that we won't have to worry about issues with the database with indexes being built in MongoDB or what have you.
- We use capistrano for deployment.
Salient points for each file:
deploy.rb: deploy:restart task should send a USR2 to the application controlled via runit.
rails-application.conf: We run unicorn in production listening on a UNIX socket behind NGINX.
rails-application.rb: Tell chef to send a USR2 to the application controller via runit.
sv-rails-application-run.erb: You need to daemonize the unicorn process with
-D. The whole file is important :)
unicorn.rb: Choose a location for the unicorn PID file that is outside of the RAILS_ROOT directory. We also needed the
before_execblock to address an issue with old releases being cleaned up by Capistrano.
Libraries for achieving zero downtime with database migrations:
- Large Hadron Migrator gem - "a gem for online ActiveRecord and DataMapper migrations."
- mysql_role_swap script - "a script written in Ruby to perform all of the tasks that we normally perform when promoting a slave database to master."
Articles and approaches for achieving zero downtime with database migrations:
- How to Create Postgres Indexes Concurrently in ActiveRecord Migrations
- Zero downtime migrations: 500 million rows...when your data is bigger than your hardware
Articles on continuous delivery and continuous deployment: