Here is the Part 3 of Deploying Rails Application on Ubuntu 14.04, and also the final part. In this part we will explain what the Capistrano template does.
Capistrano is a remote server automation and deployment tool written in Ruby. Capistrano 3 extends Rake DSL with its own set of DSL. I recommend you read the documents on Capistrano website.
Install Capistrano
In Gemfile we add the following gems,
1 2 3 4 5 6 7 8 9 10 |
|
The capistrano-rails, capistrano-bundler, and capistrano-rbenv are capistrano plugins. Let’s focus on capistrano first.
After running bundle install, if we run bundle exec cap install, it will generate following folders and files, actually when we copy the files from the capistrano template in part 2, it does the same thing.
1 2 3 4 5 6 7 8 9 |
|
- In Capfile, It requires all necessary files, and also it includes all customized tasks in lib/capistrano/tasks.
- Normally you have a production server and a staging server. So before you deploy new features to production server, you want to deploy to staging server first and after all QA are passed. So in config/deploy.rb, it defines the parameters that apply to all environments, and in config/deploy/production.rb and config/deploy/staging.rb it defines the parameters that apply to the specific environment. When we run bundle exec cap production deploy, it will load config/deploy.rb first, then config/deploy/production.rb, and then run the deploy rake task.
Understanding Capistrano
To understand Capistrano, the best way is to read its source code. Actually it’s not that hard as the source code of Capistrano is pretty easy to understand.
DSL
Capistrano defines a DSL. For those interested, can check the capistrano source code in folder lib/capistrano/dsl
Set attributes
You can set some attributes by using set, and then later use fetch to get the attribute value by key. In our sample application config/deploy.rb, you can see it sets a lot of attributes.
The following code snippets illustrate its use.
1 2 3 4 5 6 7 8 |
|
Server and Roles
Think about our deployment, at least we need a database server, an application server which is unicorn, and a web server which is Nginx or Apache. Sometimes db, app and web are on the same server, sometimes they are installed on different servers. Capistrano defines these as roles. For example, in our sample application, we define one server which has three roles,
1
|
|
So later if we want to want to do something on the server that acts as web and app role, we could use roles or release_roles method,
For example, the following code will create directory on the server that act as web and app role,
1 2 3 4 5 |
|
If the web and app role point to two different servers, each server will create the directory. If we use :all, it will get all servers.
Rake tasks
Capistrano 3 actually is an extension of Rake tasks. So when we run bundle exec cap production deploy, it will run the deploy Rake task.
Let’s have a look at the definition of the deploy task. It’s in Capistrano source code /lib/capistrano/tasks/framework.rake
1 2 3 4 5 6 7 8 9 10 |
|
So we can see that the deploy task runs the following 8 tasks in sequence, * deploy:starting * deploy:started * deploy:updating * deploy:updated * deploy:publishing * deploy:published * deploy:finishing * deploy:finished
If you are interested you should check the source code of those tasks. For example, in task deploy:updating it will invoke deploy:symlink:shared, which in turns invokes deploy:symlink:link_files, let’s see how this task is implemented
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
We can see that it will fetch the linked_files property, for our deploy sample application, we have set it to %w{config/database.yml config/secrets.yml}, so for each file, it will created a symbolic link in release_path, which points to the file in shared_path, where is release_path? Let’s have a look at Capistrano source code /lib/capistrano/dsl/paths.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
So the release_path by default is the current_path, which is the sub folder current under deploy_path, which is set by deploy_to. Since in deploy_sample application, we already set deploy_to to “/product/#{fetch(:full_app_name)}”, so for our case, release_path will be /product/deploy_sample_production/current.
For ssh, Capistrano depends on sshkit, if you are interested, you could check the documents on its website.
In Capistrano we could customize the deploy process by injecting our own tasks. For example, in config/deploy.rb in our sample application, it defines
1
|
|
So after the task deploy:symlink:shared, it will run deploy:compile_assets_locally, which is to run rake assets:precompile locally and then upload the compiled assets to the server. You could use before or after to inject tasks before or after other tasks.
So now you should have an idea how Capistrano works. It’s just a series of Rake tasks which ssh to the server to execute commands to do the deployment. In my opinion the Capistrano source code is quite easy to understand, you could check more details if you like.