Every Ruby on Rails developer tried capistrano to deploy an application without any pain. It is a great tool with lots of customizations, which can enhance it even more. The difficult thing here is that you have to look through too many useless gems and abandoned information to find a needle in a haystack and improve your productivity. Thus we decided to aggregate our experience in a single article.
1. capistrano-db-tasks
Remember how many times you had the situation when a feature worked just fine locally but threw an error 500 on staging/production? Well things like this happen from time to time and every time you have to do exactly the same boring actions to reproduce a bug:
- ssh to remote server
- check DB username and password
- dump database
- scp the dump to local machine
- restore the database from dump
It is not the full list, just the major steps, which are even boring to read. Here a gem named capistrano-db-tasks saves our time and money. It allows us leveraging configurations in deploy.rb and database.yml files to execute the whole bunch of commands.
Capistrano-db-tasks already has most of the default configurations you will need. That’s why setup process consists of two easy steps:
1. Add to Gemfile:
[ruby] gem “capistrano-db-tasks”, require: false [/ruby]
2. Add to deploy.rb:
[ruby] require ‘capistrano-db-tasks'[/ruby]
You are good to go. Run cap production db:pull and a remote database will be copied to your local database. Using cap production db:push you can reverse the process and push the data from local database to a remote one. Make sure that everybody in your team understands how the tool works. Else it is a good idea to disable pushing at all. It can be done by setting the variable disallow_pushing to true.
In addition, you get the ability to copy the assets from remote server if you need them to reproduce a bug. You can enable that by setting the assets_dir and local_assets_dir variables in the deploy.rb file.
2. capistrano-maintenance
In an ideal world, all the deployments are zero downtime and instant. But in a real world, you may come across the situation where you will not be able to execute a zero downtime deployment or it will require way too much time and money. In that case, you have to do large preliminary work.
Many companies test the whole process on a staging server and notify their users in advance via email but totally forget about a maintenance screen. In fact maintenance screen is the most vital thing to preserve users’ trust during such downtimes because even if a user did not receive your notification for some reason he will understand the situation right. He will not think that the application is broken but will see up to date information including the reason for a downtime and its estimated duration.
To simplify the whole process there is a gem capistrano-maintenance. It has pretty complex setup and we will go through it step by step.
Once you installed the capistrano-maintenance gem you should extend nginx config with:
[bash]
error_page 503 @503;
# Return a 503 error if the maintenance page exists.
if (-f /var/www/domain.com/shared/public/system/maintenance.html) {
return 503;
}
location @503 {
# Serve static assets if found.
if (-f $request_filename) {
break;
}
# Set root to the shared directory.
root /var/www/domain.com/shared/public;
rewrite ^(.*)$ /system/maintenance.html break;
}
[/bash]
We made nginx to check for …/maintenance.html file and if it is there just throw error 503 and show it instantly to the user. Now we can use capistrano task to enable maintenance without fear:
[plain] cap maintenance:enable REASON=”hardware upgrade” UNTIL=”12pm Central Time” [/plain]
And to disable maintenance:
[plain] cap maintenance:disable [/plain]
Since we understand the extensions of nginx configuration – we can easily predict the maintenance capistrano tasks behavior.
Once we enable maintenance the task composes proper maintenance.html file on the remote server. Nginx detects the file and shows its content instead of real application responses.
After that we disable maintenance, and the maintenance.html file gets removed from the server. As a result nginx starts working in usual way and serves application responses to the user.
3. capistrano_deploy_lock
Large development Teams allow finishing project fast but the difficult part is to guide every Team member and adjust the processes properly. Otherwise, you may get in huge troubles instead of development speedup.
The deployment process is a vital part of the teamwork, which should be tuned very fine. Just imagine what will happen if two developers start the deployment process at the same time. In a good case, one of them will just fail to deploy the application. But in a bad case, your Team might waste a few days to fix the result of that collision.
Capistrano_deploy_lock gem was created specifically to prevent such collisions. Under the hood, it works very straight forward. Once you start the deployment, capistrano.lock.yml file is created at the shared folder. On deployment crash the file is removed instantly.
If two developers try to deploy in parallel the first one will create capistrano.lock.yml file and continue deployment. At the same time the second developer’s deployment process will be halted because there is a lock file already. The second developer will get a message like this:
*** Deploy locked 3 minutes ago by ‘y.kaliada’
*** Message: Deploying master branch
*** Expires in 12 minutes
Finally, if you have some urgent fixes, you see a name of the developer, who does the deploy right now and you can contact him pretty fast. It will save you a lot of time if you have more than 5 developers in a Team.
4. Monit integration
Monit is considered to be a great tool to keep the whole Application infrastructure live in critical moments. Its main job is to monitor the processes and restarts them in case of any troubles. It sounds very easy and helpful, but for sure it requires the whole Team to understand how it works.
Just imagine the situation when you setup monit on the server and start deploying your application. During the deployment process sidekiq is shut down, then monit notices that and gets sidekiq back up, after that in the end of deployment process capistrano tries to get sidekiq up again. Well you have troubles.
But did you know that most of the widely known gems already have capistrano-monit integration? Yes, the story above is widely known and already fixed by utility tasks for capistrano to disable or enable monit at proper time during deployment. More than that it allows generating nice monit configuration files for gems like sidekiq and puma.
Lets look at the setup process closer and take sidekiq as an example gem. First of all we will have to install capistrano-sidekiq gem. After that we have to add the following lines to Capfile:
[ruby]
require ‘capistrano/sidekiq’
require ‘capistrano/sidekiq/monit’ #to require monit tasks
[/ruby]
Generate monit configuration template for sidekiq:
[plain] bundle exec rails generate capistrano:sidekiq:monit:template [/plain]
Adjust the configuration template and you are ready to go. On every deployment your monit configurations for capistrano will be updated with the up to date ones and monit will never break your deployment.
5. airbrush (updated: default for capistrano 3.5+)
Capistrano is a pretty verbose tool, but verbose does not mean readable. Luckily, in a developer world any too verbose tool might become readable with the help of a secondary tool. In our case airbrush disposes the information in a proper visual way and allows you looking through the logs very quickly.
Setup process might be accomplished in a very easy way.
Add to Capfile:
[ruby] require “airbrussh/capistrano” [/ruby]
Remove from deploy.rb if you have it:
[ruby] set :format, :pretty [/ruby]
Now you have a pretty logging during your deployment process and here is the example of the result output:
Summary
It was not easy to find a needle in a haystack, but experience filters useless tools and as a result you find really nice ones to help in everyday work. Now you know how to get the data from production, how to make Users happy during maintenance, adjust deployment process in a large team, use monit effectively and how to save your eyes and time for great future projects. Use our favorite tools and always struggle to find new ones, which will help you. We will be really happy to hear a few words about your favorite tools, which improve your performance and speed up the development.
2 Comments
Capistrano deploy lock (mentioned here) is for old versions.
I have a new gem for Capistrano 3.x.
https://github.com/maruf-freelancer/capistrano-deploy-lock
Great note. Thank you!