Continuous Delivery

With Capistrano

Ujjwal Ojha

Me on Github Me on Twitter ojhaujjwal

Continuous Delivery

  • Frequent releases in short cycles
  • practice of using automation to release software in short iterations
  • Goal to achieve minimal downtime and frequent updates
  • and satisfy the custom through early and continuous delivery of valuable software.

Zero Downtime Deployment

  • Bringing frequent updates to your websites/web applications
  • Without the annoying message "Site currently under maintainance"
User Waiting

A little background on traditional deployment techniques

FTP deployment

Manual deployment

  • SSH to the server
  • git pull manually
  • and maybe manually run "npm install"

Capistrano

Automating scripts on one or many servers.

Automating process of releasing new version of an application.

Capistrano is a ruby gem. But, it can be used to deploy application of any language.

How does it work?

  • No software installed on server(except Git/SVN)
  • "gem install capistrano" on local machine.
  • Executes a series of commands on a remote machine via SSH.

Release process

  • Download latest code from repository
  • Perform pre and post-deploy functions
  • like restarting web server, refreshing cache, running db migrations etc
  • Publishes the new version on deployment success

Instant rollback

Maintains multiple releases directory.

Application can be easily rolled back to the previous version.

Directory structure


app
 ├──releases
 │    ├── 20150080072500
 │    ├── 20150090083000
 │    ├── 20150100093500
 │    ├── 20150110104000
 │    └── 20150120114500
 │       ├── checked out files from Git repository
 │       └── config
 │          ├──  db.yml->/var/www/app/shared/config/db.yml
 │          └──  secret.yml->/var/www/app/shared/config/secret.yml
 │
 ├──current -> /var/www/myapp/releases/20150120114500/
 ├──repo
 │    └── VCS related data
 └──shared
      ├── linked_files and linked_dirs
         └── config
            ├── db.yml
            └── secret.yml

        

Demo Time. Hurray!

Demo Repo: http://bit.ly/2gMbkNg

Deployment Flow

        
deploy:starting    - start a deployment
deploy:started     - started hook (for custom tasks)
deploy:updating    - update server(s) with a new release
deploy:updated     - updated hook
deploy:publishing  - publish the new release
deploy:published   - published hook
deploy:finishing   - finish the deployment, clean up everything
deploy:finished    - finished hook
        
      

Installation

gem install capistrano

Deploy using: cap production deploy

Sample Capfile

          
set :deploy_config_path, 'cap/deploy.rb'
set :stage_config_path, 'cap/stages'

require "capistrano/setup"
require "capistrano/deploy"
require 'capistrano/bundler'
require 'capistrano/rails'
require 'capistrano/passenger'

# Load custom tasks from `cap/tasks/tasks` if you have any defined
Dir.glob('cap/tasks/*.rake').each { |r| import r }
          
        

Sample configuration

          
set :application, 'my_app_name'
set :repo_url, 'git@example.com:me/my_repo.git'

set :deploy_to, '/var/www/app'

set :linked_files, ['config/database.yml', 'config/secrets.yml']

set :linked_dirs, ['tmp/session', 'tmp/cache', 'backups']

namespace :deploy do
  after :updated, "composer:install"
  after :updated, "bower:install"

  after :finished, "reload:nginx"
  after :finished, "notify:finish"

  after :failed, "notify:failure"
end
          
        

Sample stage configuration

          
server 'server-ip-here',
	roles: %w{web app},
	user: 'root',
	port: 22
set :env, 'production'
set :deploy_to, "/var/www/app"
          
        

Thank you!

Any Questions?

Introcept Vacancy