Capistranoの使用方法について

スポンサーリンク

Ruby 製のデプロイツールである Capistrano の使用方法です。Rails 以外でも使用できます。

Capistranoの使い方

Gemfileにgem 'capistrano'を追加してbundle installを実行してください。インストールしたら Capistrano に必要な設定ファイルとディレクトリを作成するために次のコマンドを実行します。STAGESを省略した場合はstagingproductionのみ作成されます。

$ bundle exec cap install STAGES=dev,staging,production
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/dev.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
create Capfile
Capified

Capistrano で使用できるタスク一覧は次のコマンドで確認します。

$ bundle exec cap -T
cap deploy                         # Deploy a new release
cap deploy:check                   # Check required files and directories exist
...

共通デプロイ設定

共通のデプロイ設定はconfig/deploy.rbに記述します。様々な設定項目がありますが初めに設定するのは次のような項目です。deploy_toにはデプロイ先サーバのディレクトリを指定します。

# config valid only for current version of Capistrano
lock "3.7.2"

set :application, "capitest"
set :repo_url, "git@github.com:tasukujp/capitest.git"
ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
set :deploy_to, "/home/vagrant/projects/capitest"
set :keep_releases, 5

環境別デプロイ設定

デプロイ先の環境別の設定はconfig/deploy/{env}.rb以下のファイルに記述しますがconfig/deploy.rbの設定より優先されるため、環境毎に設定を上書きすることができます。今回はdev.rbを使用して Vagrant で作成した環境に向けてデプロイします。デプロイ先の環境には SSH でパスワード無しのログインする必要があるため鍵の場所を指定してください。

server "192.168.33.10", user: "vagrant", roles: %w{web app db}

set :ssh_options, {
  keys: %w(~/.ssh/vagrant_key),
  forward_agent: false,
  auth_methods: %w(publickey)
}

基本はデプロイ先の環境にも GitHub に登録してある SSH 用の鍵が必要ですがforward_agent: trueに設定するとコマンドを実行する環境の鍵を使うことができます。ただしデプロイ先にログインするための鍵と違う場合はkeys: %w(~/.ssh/vagrant_key ~/.ssh/id_rsa_github)のように指定してください。

デプロイ処理は SSH のログインユーザーで実行されます。以前はデフォルトで sudo を利用して root 権限で実行されていたみたいですが、set :use_sudo, falseというオプションも廃止されています。

 Upgrading from v2.x.x

デプロイ

サーバにデプロイするにはcap <env> deployコマンドを実行します。いきなり実行するのが不安であればまず以下のコマンドで確認しましょう。

$ bundle exec cap dev deploy --dry-run
$ bundle exec cap dev deploy:check

デプロイが成功するとサーバには以下のようなディレクトリが作成されます。

$ bundle exec cap dev deploy
...
vagrant@vagrant:~$ ll projects/capitest/
total 24
drwxrwxr-x 5 vagrant vagrant 4096 Jan 28 15:11 ./
drwxrwxr-x 4 vagrant vagrant 4096 Jan 28 14:39 ../
lrwxrwxrwx 1 vagrant vagrant   55 Jan 28 15:11 current -> /home/vagrant/projects/capitest/releases/20170128151136/
drwxrwxr-x 3 vagrant vagrant 4096 Jan 28 15:11 releases/
drwxrwxr-x 7 vagrant vagrant 4096 Jan 28 15:11 repo/
-rw-rw-r-- 1 vagrant vagrant  107 Jan 28 15:11 revisions.log
drwxrwxr-x 2 vagrant vagrant 4096 Jan 28 14:39 shared/
対象 用途
current 現在稼働している最新のディレクトリ。実態は releases 以下にデプロイされたディレクトリへのシンボリックリンク。
releases YYYYmmddHHMMSS形式でデプロイされるごとにディレクトリが作成される。保持するバージョンはset :keep_releases, 5で指定。
shared releasesに依存しない共通となるファイルを配置。current ディレクトリ以下には shared で作成されたファイル、ディレクトリのシンボリックリンクが作成され、稼働中のアプリはシンボリックリンクを経由して shared ディレクトリにアクセスする。

 GitHub - capistrano/capistrano: Remote multi-server automation tool

capistrano-rbenv

デプロイ先のサーバでも rbenv を使用してる場合はgem 'capistrano-rbenv'をインストールして、Capfile内のrequire "capistrano/rbenv"`を有効にします。

config/deploy.rbに設定できる値は以下の通りです。基本はデフォルトで問題ないですが .ruby_version を使用して rbenv のバージョンを指定してる場合はset :rbenv_ruby, File.read('.ruby-version').stripを記述して下さい。:rbenv_typeは rbenv のインストール先がデプロイ先ユーザーのホームディレクトリであれば:userを、/usr/local/rbenv であれば:systemを指定します。

set :rbenv_type, :user
set :rbenv_ruby, '2.0.0-p247'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}
set :rbenv_roles, :all

 GitHub - capistrano/rbenv: Idiomatic rbenv support for Capistrano 3.x
GitHub - capistrano-plugins/capistrano-safe-deploy-to

capistrano-bundler

デプロイされたプロジェクトディレクトリを見ると Gem が Bundler でインストールされていません。デプロイと同時にbundle installを実行したい場合はgem 'capistrano-bundler'をインストールして、Capfile内のrequire "capistrano/bundler"を有効にします。

プラグインが追加されるとbundle exec cap -Tでタスクが増えてるのを確認できます。

config/deploy.rbに設定できる値は以下の通りです。

set :bundle_roles, :all                                         # this is default
set :bundle_servers, -> { release_roles(fetch(:bundle_roles)) } # this is default
set :bundle_binstubs, -> { shared_path.join('bin') }            # default: nil
set :bundle_gemfile, -> { release_path.join('MyGemfile') }      # default: nil
set :bundle_path, -> { shared_path.join('bundle') }             # this is default. set it to nil for skipping the --path flag.
set :bundle_without, %w{development test}.join(' ')             # this is default
set :bundle_flags, '--deployment --quiet'                       # this is default
set :bundle_env_variables, {}                                   # this is default
set :bundle_clean_options, ""                                   # this is default. Use "--dry-run" if you just want to know what gems would be deleted, without actually deleting them

デフォルト設定のままだと--without development testオプション付きで実行されてしまうため、staging や production 以外の dev 環境などにデプロイしたい場合はset :bundle_without, nilを環境別の設定ファイルconfig/deploy/dev.rbに記述する必要があります。また、Gem のインストール先はsharedディレクトリ配下です。

without を無効にして実行すると次のようになります。

$HOME/.rbenv/bin/rbenv exec bundle install --path /home/vagrant/projects/bookshelf/shared/bundle --deployment --quiet

 GitHub - capistrano/bundler: Bundler support for Capistrano 3.x

capistrano-rails

DB の migration や assets の precompile を実行するためにgem 'capistrano-rails'をインストールして、Capfile 内のrequire "capistrano/rails/assets"require "capistrano/rails/migrations"を有効にします。

config/deploy.rbに設定できる値は以下の通りです。set :rails_env, 'staging'は環境別の設定ファイルで指定してください。

set :rails_env, 'staging'   # If the environment differs from the stage name
set :migration_role, :db   # Defaults to :db role
set :migration_servers, -> { primary(fetch(:migration_role)) }   # Defaults to the primary :db server
set :conditionally_migrate, true   # Defaults to false. Skip migration if files in db/migrate were not modified
set :assets_roles, [:web, :app]   # Defaults to [:web]
set :assets_prefix, 'prepackaged-assets'   # Defaults to 'assets'. This should match config.assets.prefix in your rails config/application.rb
set :normalize_asset_timestamps, %w{public/images public/javascripts public/stylesheets}   # If you need to touch public/images, public/javascripts, and public/stylesheets on each deploy
set :keep_assets, 2   # Defaults to nil (no asset cleanup is performed). If you use Rails 4+ and you'd like to clean up old assets after each deploy, set this to the number of versions to keep

Rails の設定ファイルやディレクトリなどのシンボリックリンクを作成することができます。これは releases に依存しない共通となるファイルやディレクトリを配置するためのものです。そのため shared ディレクトリ内に実態のディレクトリとファイルが置かれるので、releases に最新のディレクトリがデプロイされても前回のファイルがそのまま使用できます。file に関してはあらかじめsharedディレクトリ内に作成しなければいけない事に注意して下さい。よくある使い方としてはdatabase.yml.sampleなどでリポジトリ管理しておいて、実際にはdatabase.ymlにコピーして使う方法などです。

set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system', 'public/uploads')
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')

 GitHub - capistrano/rails: Official Ruby on Rails specific tasks for Capistrano