はじめに
アプリを本番環境にアップロードして誰でもアクセスできる状態にすることをデプロイと言います。デプロイで行うべきことは多岐にわたります。Railsアプリの場合で言えば、本番環境にアップロードすることはもちろんですが、Gemのインストールやマイグレーション、SprocketsやWebpackerのコンパイルなど多くのことを行う必要があります。これらの作業を毎回すべて手作業で行うのは骨が折れますし、いつもヒューマンエラーを起こさないとも限りません。Capistranoというデプロイツールを使えば面倒なデプロイ作業を自動化することができます。
本記事では、デプロイツール「Capistrano」の使い方をまとめています。
Capistranoの基本
Capistranoについて
Capistrano(カピストラーノ)とは、アプリのデプロイ作業を自動化するツールです。Rubyで作られていますが、Rubyで作られたアプリ(Railsアプリなど)以外のデプロイ作業でも使うことができます(Rubyの実行環境は必要)。
Capistranoは学習コストが高いと言われており、初学者には少し敷居が高いかもしれません。確かに、Capistranoの設定は複雑で大変な作業です。しかし、一度設定してしまえばその後の面倒なデプロイ作業がすべて自動化できるので、無理してでも導入すべきではないかと思います。
Capistranoの構成
Capistranoは大まかに分けると3つの要素で構成されています。
要素 | 説明 |
---|---|
設定 | アプリの情報やデプロイ先サーバーの情報などを設定します。共通のデプロイ設定と、デプロイ環境(本番環境/ステージング環境)ごとの設定があります。 |
タスク | 前述の設定に基づいてデプロイ先サーバーで行うタスクを定義します。なお、フレームワーク固有の基本タスク(Gemのインストールやマイグレーションなど)は後述するライブラリに含まれているので、開発者が定義すべきアプリ固有のカスタムタスクはそれほど多くありません。 |
ライブラリ | 各種セットアップやデプロイに係る基本タスク(サーバー接続やリポジトリからの取得など)、フレームワーク固有の基本タスクが含まれています。必要に応じてライブラリを追加することでデプロイ作業に組み込むことができます。 |
Capistranoのインストール
Gemfile
に以下を追記し、bundle install
を行います。Capistrano本体以外にも追加のライブラリをインストールしています。
Gemfile
group :development do
# 以下を追記
gem 'capistrano'
gem 'capistrano-rbenv'
gem 'capistrano-bundler'
gem 'capistrano-rails'
end
なお、後述する「Capistranoの設定」セクションでCapistranoのバージョン指定を行っています。Capistranoのバージョンが上がるたびにその設定も変更する必要があるので、それが嫌だという場合はバージョンを指定してインストールしてください。
Gemfile
の書き方については以下の記事を参照してください。
以下のコマンドを実行してCapistranoをインストールします。
$ bundle exec cap install
上記のコマンドを実行すると以下のファイルが作成されます。これらの設定やタスクについては「Capistranoの設定」セクションで説明します。
/
|-config/
| |-deploy/ # 環境ごとのデプロイ設定
| | |-production.rb # 本番環境のデプロイ設定
| | |-staging.rb # ステージング環境のデプロイ設定
| |
| |-deploy.rb # 共通のデプロイ設定
|
|-lib/
| |-capistrano/
| |-tasks/ # カスタムタスク
|
|-Capfile # Capistranoの基本設定
Capistranoの実装
Capistranoはカスタマイズ性の高いデプロイツールのため、好みによっていろいろなデプロイ方法を設定することができます。今回は例として、概ね以下の流れでデプロイを行うようCapistranoを構成していきます。なお、前提としてバージョン管理システムへのアップロードは手動で行っておく必要があります。
- デプロイ先サーバーへSSH接続
- デプロイ先サーバーからバージョン管理システムへ接続
- バージョン管理システムから最新版のアプリケーションをクローン
- フレームワーク固有の基本タスク(マイグレーションなど)を実行
- アプリケーションサーバーの起動または再起動
Capistranoの基本設定
Capistranoの基本設定はCapfile
で行います。
Capfile
# DSLの読み込みと環境ごとの設定
require "capistrano/setup"
# デフォルトタスクの読み込み
require "capistrano/deploy"
# 追加ライブラリ(Git)の読み込み
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
# 追加ライブラリ(その他)の読み込み
require "capistrano/rbenv"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
# カスタムタスクのインポート
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
基本的にCapistranoをインストールした直後の状態から変更する必要はありませんが、「Capistranoのインストール」セクションで追加のライブラリをインストールしている場合はここで読み込む設定を行います。
共通のデプロイ設定
共通のデプロイ設定はconfig/
ディレクトリ配下のdeploy.rb
で行います。
deploy.rb
# Capistranoのバージョン
lock "~> 3.16.0"
# アプリケーション固有の設定
set :application, "my_app_name"
set :repo_url, "git@example.com:me/my_repo.git"
set :branch, 'master'
set :deploy_to, '/var/www/my_app_name'
set :linked_files, %w(config/master.key)
set :linked_dirs, %w(log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system)
set :keep_releases, 5
set :rbenv_ruby, '2.6.3'
set :log_level, :debug
set :default_env, {
rbenv_root: "/home/user/.rbenv",
path: "/home/user/.rbenv/bin:$PATH"
}
lock
でCapistranoのバージョンを固定します。インストールされているCapistranoのバージョンはGemfile.lock
で確認できます。バージョン指定にはGemfile
と同じ方法を使うことができます。
set
で設定した値はfetch
で取得します(タスクで使用)。今回設定している項目は以下の通りです。
設定 | 説明 |
---|---|
:application |
デプロイするアプリの名称。 |
:repo_url |
バージョン管理システムのリポジトリURL。 |
:branch |
リポジトリのブランチ。デフォルトはmaster 。 |
:deploy_to |
デプロイ先のディレクトリ。 |
:linked_files |
シンポリックリンクを貼るファイル。 |
:linked_dirs |
シンポリックリンクを貼るディレクトリ。 |
:keep_releases, |
保持するリリースバージョンの数。 |
:rbenv_ruby |
デプロイ先サーバーにインストールされているRubyバージョン。 |
:log_level |
出力するログレベル。 |
:default_env |
デプロイ先サーバーに設定する環境変数。 |
:linked_files
では、バージョン管理システムへはアップロードされないがデプロイ先サーバーには必要なファイルを設定します。今回はCredentialsを使用しているのでconfig/master.key
を設定しています。
環境ごとの設定
環境ごとの設定はconfig/deploy/
ディレクトリ配下のファイルで行います。Capistranoのインストール時に本番環境とステージング環境の設定ファイルが作成されますが、今回はステージング環境にデプロイは行わないのでstaging.rb
は削除します。
production.rb
server 'xxx.xxx.xxx.xxx',
user: 'xxxxx',
roles: %w{app db web},
port: xxxxx,
ssh_options: {
keys: '~/.ssh/id_rsa'
}
roles
はタスクを実行するための権限を設定します。タスクには実行権限を設定することができます。ここで設定した権限以外がタスクに設定されている場合、そのタスクは実行されません。
サーバーへの接続にSSHを使用している場合、ssh_options
でローカルにある鍵ファイルのパスを設定します。また、SSHで使用するポート番号を変更している場合はport
で設定します(デフォルトは22
)。
カスタムタスク
追加ライブラリに含まれるフレームワーク固有の基本タスク以外に実行すべきタスクがある場合はカスタムタスクを作成します。lib/capistrano/tasks/
ディレクトリ配下にcustom.rake
を作成し、以下を記述します。
custom.rake
after 'deploy:publishing', 'deploy:restart'
namespace :deploy do
desc 'Restart unicorn server'
task :restart do
on roles(:app) do
invoke 'unicorn:restart'
end
end
end
一行目のafter
はタスクが実行される順番を設定しています。deploy:publishing
が実行されてからdeploy:restart
を実行するようにしています。ちなみにdeploy:publishing
はライブラリに含まれる基本タスクのひとつです。before
とafter
は名前空間ブロックの中で書くこともでき、その場合名前空間を省略してタスクを指定することができます。
namespace :deploy do
after 'publishing', 'restart'
end
on roles
でタスクの実行権限を設定しています。deploy:restart
は:app
という権限を設定していなければ実行されません。
invoke
でunicorn:restart
(unicorn
という名前空間にあるrestart
というタスク)を呼び出しています。このタスクはまだ未定義なので、これから作成していきます。lib/capistrano/tasks/
ディレクトリ配下にunicorn.rake
を作成し、以下を記述します。
unicorn.rake
namespace :unicorn do
task :environment do
set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid"
set :unicorn_config, "#{current_path}/config/unicorn.rb"
end
def start_unicorn
within current_path do
execute :bundle, :exec, :unicorn, "-c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
end
end
def stop_unicorn
execute :kill, "-s QUIT $(< #{fetch(:unicorn_pid)})"
end
def restart_unicorn
execute :kill, "-s USR2 $(< #{fetch(:unicorn_pid)})"
end
def force_stop_unicorn
execute :kill, "$(< #{fetch(:unicorn_pid)})"
end
desc "Start unicorn server"
task start: :environment do
on roles(:app) do
start_unicorn
end
end
desc "Stop unicorn server gracefully"
task stop: :environment do
on roles(:app) do
stop_unicorn
end
end
desc "Restart unicorn server gracefully"
task restart: :environment do
on roles(:app) do
if test("[ -f #{fetch(:unicorn_pid)} ]")
restart_unicorn
else
start_unicorn
end
end
end
desc "Stop unicorn server immediately"
task force_stop: :environment do
on roles(:app) do
force_stop_unicorn
end
end
end
deploy:restart
から呼び出されたunicorn:restart
では、Unicornの起動状態を調べ、起動している場合は再起動し、起動していない場合は起動します。その他のタスク(Unicornの開始や停止)について詳しくは以下の記事を参照してください。
Capistranoの実行
Capistranoの各種設定やタスク定義ができたら、以下のコマンドを実行してデプロイを行います(注意:本記事の内容だけではUnicornの設定を行っていないのでコマンドは失敗します)。
$ bundle exec cap production deploy [--dry-run]
cap
コマンドの第1引数はデプロイ環境を指定します。config/deploy/
ディレクトリ配下にある設定ファイルの名前(拡張子を除く)を指定します。
第2引数は名前空間を指定します。指定した名前空間に含まれるすべてのタスクが実行されます。デフォルトタスクの名前空間はdeploy
なので、通常はこれを指定します。また、特定のタスクのみを実行することもできます。以下はデプロイ先サーバーでUnicornの再起動を実行しています。
$ bundle exec cap production unicorn:restart
以下のコマンドを実行すると、実行可能なタスクの一覧を確認することができます。
bundle exec cap -T
--dry-run
オプションをつけると実際のデプロイは行われず、各種設定やタスクが正常に動作するかを確認できます。
今回はデプロイ先サーバーへの接続にSSHを使用しているので、上記のコマンドを実行した後にSSH接続のパスワードの入力を求められます。パスワードを入力するとデプロイタスクが続々と行われていきます。
Capistranoの完全な実行ログはlog/
ディレクトリ配下のcapistrano.log
で確認できます。デプロイ中にエラーが起こった場合はまずこのファイルを見てエラー内容を把握しましょう。
まとめ
Capistranoはよく学習コストが高いと言われます。しかし、デプロイに必要なタスクはライブラリで用意されていることが多いので、自分で定義するタスクの量はそれほど多くありません。記述すべきファイルが多くて大変そうだと思うかもしれませんが、実は設定もタスクもひとつのファイルにまとめてしまうこともできます。ただし、その場合はメンテナンス性が落ちるので、ファイルはわかりやすい単位で分けることをおすすめします。
本記事を参考にして、Capistranoの使い方を覚えていただければと思います。