Ruby 製のデプロイツールである Capistrano の使用方法です。Rails 以外でも使用できます。
Capistranoの使い方
Gemfileにgem 'capistrano'
を追加してbundle install
を実行してください。インストールしたら Capistrano に必要な設定ファイルとディレクトリを作成するために次のコマンドを実行します。STAGES
を省略した場合はstaging
とproduction
のみ作成されます。
$ 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
というオプションも廃止されています。
デプロイ
サーバにデプロイするには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