【入門】Capistrano3で自動デプロイ
※この記事はcapistrano3についてです。capistrano2.x系には対応していません。
ちょこちょこ新規開発しているのですが、毎回リモートサーバーにsshで入って
pullして手順見ながらbundleなんちゃらして・・・。
みたいなのが非常にめんどくさいので、capistranoを使ってみました。
一度覚えてしまうと楽チンなので損はないと思います!そんなに難しくないです!
今回はインストールから実際のデプロイまで順を追って説明していきたいと思います。
★やろうとしていること
- Rails4のアプリをリモートサーバーにローカルからデプロイ
- web, db, appサーバーはとりあえず同じサーバーで
- git pullとかassets:precompileとかmigrationとか自動でやりたい
- テスト的にvagrantで作った仮想環境にデプロイするまでを説明します。
★できてないこと
- unicornのhot deploy
■環境
- Ruby2.1.1(あまり今回は関係ない)
- rbenvを使っている
- vagrant(CentOS6.4)
まずcapistranoの導入です。Gemfileに書くだけなので超簡単です。
# Gemfile group :development do gem :capistrano gem :capistrano-rails gem :capistrano-bundler gem :capistrano-rbenv end
そしてあとはいつもどおりインストール。
$ bundle install
さて、ここまでできたらcapistranoのデフォルトファイル群を用意します。
これもコマンドひとつでできます。
$ bundle exec cap install mkdir -p config/deploy create config/deploy.rb create config/deploy/staging.rb create config/deploy/production.rb mkdir -p lib/capistrano/tasks Capified
こんな感じでいくつかファイルが出来たと思います。
この時オプション指定でdevelopmentを作ったりもできます。
今回はstagingを使ってvagrantにテストデプロイしていきます。
Capfile
まずはここからいきましょう。とりあえずいろいろ書かれていますが全部消しちゃっていいです。
require 'capistrano/setup' require 'capistrano/deploy' require 'capistrano/rails' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/rbenv' require 'capistrano/bundler' # Loads custom tasks from `lib/capistrano/tasks' if you have any defined. Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
使うものをrequireしているだけです。これでOK。
config/deploy/staging.rb
次にデプロイ先の環境を設定しましょう。今回はvagrantにデプロイします。
set :stage, :staging role :app, %{vagrant@デプロイ先IP} role :web, %{vagrant@デプロイ先IP} role :db, %{vagrant@デプロイ先IP}
config/deploy.rb
これがメインとなるファイルです。ここにデプロイのtaskを書いていきます。
と、その前にデプロイ後どういうディレクトリ構造になるのかというのを知っておいたほうが理解しやすいと思うので下に図示しておきます。
[vagrant@localhost ~]$ tree アプリ名/ -L 2 アプリ名/ ├── current -> /home/vagrant/アプリ名/releases/20140421075958 ├── releases │ ├── 20140421062631 │ ├── 20140421064312 │ ├── 20140421064620 │ ├── 20140421074708 │ └── 20140421075958 ├── repo │ ├── FETCH_HEAD │ ├── HEAD │ ├── branches │ ├── config │ ├── description │ ├── hooks │ ├── info │ ├── objects │ ├── packed-refs │ └── refs ├── revisions.log └── shared ├── bin ├── bundle └── public 17 directories, 6 files
上のように、capistranoは[current, releases, repo, shared]という4つのディレクトリを作ります。
releasesにリリースごとのバージョンが管理されていき、currentはreleasesの最新へのシンボリックリンクになっているという感じです。
その他のディレクトリについてはまた調べてみてください。
では、config/deploy.rbに戻りましてとりあえず必要最低限のところから設定していきましょう。
# config valid only for Capistrano 3.1 lock '3.1.0' set :application, 'アプリ名' set :repo_url, 'cloneしてくるレポジトリのURL.git' set :branch, 'master' # デフォルトがmasterなのでこの場合書かなくてもいいです。 set :deploy_to, "/home/vagrant/アプリルートディレクトリ" set :scm, :git # capistrano3からgitオンリーになった気がするのでいらないかも? set :format, :pretty set :log_level, :debug # :info or :debug set :keep_releases, 3 # 何世代前までリリースを残しておくか set :rbenv_type, :user set :rbenv_ruby, '2.1.1' 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 # default value
こんな感じでしょうか。
set :key, :valuie
のような構造になっています。
さて、いよいよデプロイ時に走らすタスクを書いていくというフェーズなのですが、
実はcapistranoはもともとデフォルトで既にいくつかのタスクを用意しています。
$ bundle exec cap -T
とやるとタスクの一覧が見れるのでみてみましょう。
cap bundler:install # Install the current Bundler environment cap bundler:map_bins # Maps all binaries to use `bundle exec` by default cap deploy # Deploy a new release cap deploy:check # Check required files and directories exist cap deploy:check:directories # Check shared and release directories exist cap deploy:check:linked_dirs # Check directories to be linked exist in shared cap deploy:check:linked_files # Check files to be linked exist in shared cap deploy:check:make_linked_dirs # Check directories of files to be linked exist in shared cap deploy:cleanup # Clean up old releases cap deploy:cleanup_assets # Cleanup expired assets cap deploy:cleanup_rollback # Remove and archive rolled-back release cap deploy:compile_assets # Compile assets cap deploy:finished # Finished cap deploy:finishing # Finish the deployment, clean up server(s) cap deploy:finishing_rollback # Finish the rollback, clean up server(s) cap deploy:log_revision # Log details of the deploy cap deploy:migrate # Runs rake db:migrate if migrations are set cap deploy:normalize_assets # Normalize asset timestamps cap deploy:published # Published cap deploy:publishing # Publish the release cap deploy:restart # Restart application cap deploy:revert_release # Revert to previous release timestamp cap deploy:reverted # Reverted cap deploy:reverting # Revert server(s) to previous release cap deploy:rollback # Rollback to previous release cap deploy:rollback_assets # Rollback assets cap deploy:started # Started cap deploy:starting # Start a deployment, make sure server(s) ready cap deploy:symlink:linked_dirs # Symlink linked directories cap deploy:symlink:linked_files # Symlink linked files cap deploy:symlink:release # Symlink release to current cap deploy:symlink:shared # Symlink files and directories from shared to release cap deploy:updated # Updated cap deploy:updating # Update server(s) by setting up a new release cap install # Install Capistrano, cap install STAGES=staging,production
よく見てみると、すでにgit pullやrake db:migrateやassets:precompuleも用意されています。
なのでミニマムではタスクは何も書かなくてもよいでしょう。
でもせっかくなのでDBがデプロイ時になければ作成するというタスクを追加しておきましょう。
# デプロイ前に実行する必要がある。 desc 'execute before deploy' task :db_create do on roles(:db) do |host| execute "mysql -uroot -e 'CREATE DATABASE IF NOT EXISTS データベース名;'" end end
これはnamespace :deployの外に書いて個別に実行すると良いと思います。
いくつかタスクについて説明すると、まずnamespaceで名前空間を切ってそれぞれを管理できます。
あとはrolesというのがポロポロ出てきていると思うのですが、これは例えばroles(:db)としておくと、dbサーバーに対してのみ実行します。(dbサーバーはconfig/deploy/以下で指定したものですね。)
taskの前にdescを書くことが出来て、タスクの説明なんかも残しておけます。
デプロイ
さて、ここまでくれば後は実際にデプロイするのみです。 ローカルからdeployコマンドをうってみましょう。
$ bundle exec cap db_create $ bundle exec cap staging deploy
うまくできましたか?本番リリース時はstagingのところをproductionにしてデプロイして下さい。
余談
僕が導入しようと思った環境はsupervisor経由でunicornを動かしていて、リリースごとにsupervisorを再起動する必要があります。
なのでsupervisorの再起動中に503がでてしまって"ゔッ!"ってなるのでcapistrano経由でunicornのホットデプロイをできないかとも
考えていたのですが、そもそもsupervisorを使ったunicornのホットデプロイのベストプラクティスがわかっておらず、
(先輩が調べてくれたのですがなかなかやっかいそう…)
そこんとこまだ完全に自動化しきれていないなー、、というのが現状です。。
ともかくcapistrano自体の導入はそれほど敷居は高くないので導入してみてはいかがでしょうか!(๑╹ڡ╹๑)