Ok, you did it. You wrote your blog in 15 minutes. Or maybe you created your change-of-the-world app during startup weekend. Or you finally finished bootstrapping an application for your customer and now you have to find a stage for it. There are many possible situations but with every client-server project you will eventually have to do it: deploy a Ruby on Rails web app.
Ruby on Rails deployment
There are two main things to discuss regarding Ruby on Rails deployment process. The first is how RoR-based app runs on server. The second is the script set for deployment automation, which is a way to set up your app on the server and keep it updated as it grows.
How Ruby on Rails works on server
A Ruby application needs an app server, actually a Rack server – a piece of software that takes your code, runs it, listens to a port or Unix socket, runs your code on incoming requests and writes your responses to that port or socket. In the Rails world it is typically Thin, Unicorn or Puma, sometimes - Passenger.
These servers provide concurrency in very different ways: using EventMachine with Thin, utilizing native threads on Puma, running multiple copies of application on Unicorn or whatever they do in Passenger. Sorting out the differences between them is worth a separate article and it will be published under "Ruby on Rails deploy explained series." For now, I advise you to go with Thin and scale with Rubinius and Puma only when you find out that you need better performance or concurrency level.
In addition, Rails application in production is usually served via a web server, de facto – Nginx, set in a reverse proxy mode for the rack server running.
The responsibilities between app server and web server are shared so that you may think of an app server as a responsibility of a developer and web server as a responsibility of an admin.
The usual actions which you must perform to deploy:
- Bring your code to server.
- Bundle the dependencies, both installing gems and required binaries.
- Provide backing services (database).
- Launch / restart app server in a correct way.
- Set up a reverse proxy in Nginx.
Capistrano, Vlad, Mina, whatever similar (Fabric?)
On its own, Capistrano is a way to execute commands on a remote server or servers via SSH. But when we say Capistrano we usually mean some common approach with already prepared scripts that you just have to configure declaratively and they will do the stuff. This includes building application, providing configuration, launching / relaunching and possibly exposing the launched app to public.
At the beginning, Ruby on Rails app deployment using Capistrano 3 looks simple and straightforward. However there are some drawbacks.
First of all the solution you find will most likely be non-production ready. For instance, your application won't start automatically after a server reboot. When you get it, you will start investigating, learn about Upstart and write your own service. But this will lead you to the next problem.
Now the server knows too much about application and this knowledge has to be stored somewhere. Keeping an eye on all the things, such as Ruby version, which process to run and how to restart it, will greatly limit your portability. You will start googling and will find out about Ansible if you are lucky and about Chef if you are not.
This will introduce you to a new exciting world of setting up server configuration, infrastructure as code, etc. What seemed to be a simple task, will evolve into a separate repository with its own configuration, another language and lots of choices (rvm? rbenv? upstart? runit? configuration files? environment variables? logrotate? rsyslog?).
What if there would be a convention – how to configure application, how to start, how to execute, where the logs are – and so server could be generic? There are some options for that, let's review them.
Heroku claims to be a platform as a service (PaaS). It says, "Give me the code and I will run it. You'll have your application launched here, logs here and you can configure it here."
In order to deploy a Ruby on Rails web app on Heroku, you should make some changes to the application, so that it will be "standard". In contrast to Capistrano, your application becomes clean of the deployment details and only contains the application code - no Capfile, no
config/deploy.rb. Some special files are still required but their semantics are different – they describe how to run the application.
Honestly, Heroku is great. It, however, has one major drawback – it's expensive. This fact brings us to a very novel idea that you can run your own PaaS.
Dokku is a piece of software that allows you to turn a single server into mini-heroku. It provides the same good features as Heroku but for the price of the hardware, which, thanks to Digital Ocean, is very comfortable now.
You do the same things that you have to do to prepare your application to Heroku. In fact, it will be also Heroku-ready and, just in case, ready to most of the other existing PaaS solutions. After that you'll need around 20 minutes to deploy your app and around 5 minutes to deploy each next application.