&tag(Capistrano3); *目次 [#h2c8944f] #contents *関連ページ [#p990e6ae] -[[Capistrano]] -[[./アップグレード]] *参考情報 [#i3b863a7] -[[capistrano/CHANGELOG.md at master · capistrano/capistrano:https://github.com/capistrano/capistrano/blob/master/CHANGELOG.md]] -[[Upgrading from v2.x.x:http://capistranorb.com/documentation/upgrading/]] -[[capistrano 3.x系を使ってrailsをデプロイ | iii ThreeTreesLight:http://threetreeslight.com/post/68344998681/capistrano-3-x-rails]] -[[capistrano をバージョン 3 にアップデートして時代の流れに乗る - けんごのお屋敷:http://tkengo.github.io/blog/2013/12/12/version-up-capistrano-v3/]] … v2との違いなど -[[入門 Capistrano 3 ~ 全ての手作業を生まれる前に消し去りたい | GREE Engineers' Blog:http://labs.gree.jp/blog/2013/12/10084/]] … 丁寧な解説。 *基本的な使用方法[#v40b5c7b] 以下bundle経由で使用する方法を説明する。 **V2からの移行 [#bbc60870] -互換性がないので作りなおさないといけない。 -GemfileをCapistrano3用に変更し、 -Capfile、config/deploy.rbを削除し、 -以下のインストール移行の手順を実行する。 **設定値の違い [#sdbc9dc6] -:repositoryが:repo_urlに。 -ssh_optionsの指定方法が。 ** インストール [#tebcad30] -Gemfileを編集し以下を追加。基本は"capistrano"だけだが、railsの処理を行ったり、rbenvの処理を行ったり、bundleを実行したりする場合追加のgemが必要となる。 #pre{{ group :deployment do gem 'capistrano' gem 'capistrano-rails' gem 'capistrano-rbenv' gem 'capistrano-bundler' end }} -gemのインストール bundle install --path vendor/bundle **設定ファイルの作成 [#adc54f37] -プロジェクトフォルダに移動し、「cap install」を実行 #pre{{ $ cd myproject $ 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 }} **設定ファイルの編集 [#d28259dc] ***Capfile [#sb5ee752] -Capfileでは使用するモジュールをrequireする。他のファイルでrequireしてもうまくいかなかったりするの注意。 #pre{{ # Load DSL and Setup Up Stages require 'capistrano/setup' # Includes default deployment tasks require 'capistrano/deploy' # Includes tasks from other gems included in your Gemfile # # For documentation on these, see for example: # # https://github.com/capistrano/rvm # https://github.com/capistrano/rbenv # https://github.com/capistrano/chruby # https://github.com/capistrano/bundler # https://github.com/capistrano/rails # # require 'capistrano/rvm' require 'capistrano/rbenv' # require 'capistrano/chruby' require 'capistrano/bundler' require 'capistrano/rails/assets' #require 'capistrano/rails/migrations' # Loads custom tasks from `lib/capistrano/tasks' if you have any defined. Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } }} ***config/deploy/staging.rbの編集 [#m5ee541e] -いきなり本番サーバーにdeployするのは危険性が高い。テスト用の環境にデプロイするためstaging.rbを準備する。 #pre{{ server 'centos6vm', user: 'tanaka', roles: %w{app db web}, my_property: :my_value role :app, %w{tanaka@centos6vm} role :web, %w{tanaka@centos6vm} role :db, %w{tanaka@centos6vm} }} ***config/deploy/production.rbの編集 [#s166c17f] -production環境に関する設定を行う。role、server、ssh_optionsの設定あたり。 ***config/deploy.rbの編集 [#mb74ff23] -デプロイに関する共通設定を記述する。以下は後述するcopy_to_deployを実行する設定。 -デプロイだけだとデバッグが大変なのでリモートで"ls"を実行する「list」タスクを定義しておくと便利。 #pre{{ set :application, 'demoapp' set :rbenv_ruby, File.read('.ruby-version').strip set :scm, :copy set :tar_roles, :web set :exclude_dir, ['vendor/bundle'] set :bundle_flags, '--quiet' task :list do on roles(:web) do execute "ls" end end namespace :deploy do namespace :deploy do after :restart, :restart_passenger do on roles(:web), in: :groups, limit: 3, wait: 10 do within release_path do execute :touch, 'tmp/restart.txt' end end end after :finishing, 'deploy:restart_passenger' end end }} ** 使用する [#r43bb852] **listタスクの実行 [#l2ce8f89] -サーバー上で"ls"を実行するlistタスクを実行してみる bundle exec cap staging list **deployタスクの実行 [#u1750759] -サーバー上にdeployする bundle exec cap staging deploy *Tips [#b1c4e757] **passengerを再起動したい [#kc27af13] -apache passengerはtmp/restart.txtを見て再起動してくれる。 -そこで以下のような設定をdeploy.rbに追加しておくといいらしい。 #pre{{ namespace :deploy do after :restart, :restart_passenger do on roles(:web), in: :groups, limit: 3, wait: 10 do within release_path do execute :touch, 'tmp/restart.txt' end end end after :finishing, 'deploy:restart_passenger' end end }} -passengerは再起動したあとtmp/restart.txtを削除するという説としないという説がある。 -再起動したかどうかログにも書き出されずよくわからない。 **deploy_via:copyしたい(capistrano-scm-copy編) [#u725bdde] -[[wercker/capistrano-scm-copy:https://github.com/wercker/capistrano-scm-copy]]を使う方法。 ***設定 [#fddf8ec0] -Gemfileに以下を追加する gem "capistrano-scm-copy" -config/deploy.rbの:scmを変更。exclude_dirに指定したディレクトリは無視される。 set :scm, :copy set :exclude_dir, ['vendor/bundle'] -staging.rb、production.rbの変更 -deploy_toでdeploy先ディレクトリを指定する。staging、production環境で異なる場合deploy.rbではなくstaging.rbかproduction.rbで変更しないといけない。 #pre{{ set :deploy_to, '/home/tanaka/www/demoapp' }} -公式ドキュメントによろと、Capfileに以下を追加する必要がある。 require 'capistrano/copy' -しかし、[[Appears to try to upload archive file 2x · Issue #17 · wercker/capistrano-scm-copy:https://github.com/wercker/capistrano-scm-copy/issues/17]]によると、処理が2回走ってしまうためrequireしてはならない。 #pre{{ I had the same problem but could find a proper solution; remove require 'capistrano/copy' anywhere! This problem occurs when we use this module with capistrano/setup because capistrano/setup loads a scm module with the :scm value. https://github.com/capistrano/capistrano/blob/master/lib/capistrano/setup.rb#L18 Good luck! }} **deploy_via:copyしたい(自作編) [#n43b9a84] -デフォルトではできなくなっているので、[[Capistrano3 で deploy_via :copy する - Qiita:http://qiita.com/hidakatsuya/items/4d097416516afc229199]]を参考にする。 -Gemfileにrubyzipを追加。 #pre{{ group :deployment do gem 'capistrano', '~> 3.0', require: false gem 'rubyzip', require: false end }} -lib/capistrano/tasks/copy.rakeを作成。上記リンクからちょっとカスタマイズ。 #pre{{ require 'zip' Zip.setup do |c| c.unicode_names = true c.on_exists_proc = true c.continue_on_exists_proc = true end namespace :copy do task :check do end task :set_current_revision do end task create_release: 'release.zip' do |t| file = t.prerequisites.first on roles(:app) do execute :mkdir, '-p', fetch(:tmp_dir) upload! file, fetch(:tmp_dir) execute :unzip, '-o', "#{fetch(:tmp_dir)}/release.zip", '-d', release_path end File.delete file if File.exists?(file) end file 'release.zip' do |t| release_filename = File.join(Dir.pwd, t.name) Dir.chdir fetch(:copy_dir) do Zip::File.open(release_filename, Zip::File::CREATE) do |zipfile| files = FileList['**/*'] files.exclude(*fetch(:copy_exclude)).each do |file| zipfile.add(file, file) end end end end end }} -deploy.rbを編集して完了。 #pre{{ set :scm, 'copy' set :copy_dir, '.' set :tmp_dir, '/tmp' set :copy_exclude, [ /\.log$/, %r!^files/.+! ] }} -copy_excludeのパターンは、 Rake::FileListの、excludeで指定できるパターン。[[class Rake::FileList:http://docs.ruby-lang.org/ja/2.0.0/class/Rake=3a=3aFileList.html#I_EXCLUDE]]。パターンとして正規表現、グロブパターン、文字列が使用可能。 -FileList['**/*']はプロジェクトルートからの相対パスを返してくるので、例えば railsプロジェクトの、logs、vendor以下を除外したい場合、以下のように指定するとよさそう。 #pre{{ set :copy_exclude, [ /^logs/, /^tmp/, /^vendor/ ] }} -ドットファイル(.で始まるファイル)がコピーされないけど、それはそれでいいのか?(特にruby-versionとか)。 *FAQ [#v91a0669] **ロールってなに? [#p9dcdd23] -サーバーごとに役割を設定するもの。[[Rails - はじめてのCapistrano - Qiita:http://qiita.com/mosson/items/1a4cfd01cb538f2d8f0e]]の説明がわかりやすいかも。Capistrano3もCapistrano2も考え方に大差はない。 -Capistranoではタスクは、デフォルトでは全ロール、全サーバーに対して実行できる。タスクに対し例えばwebロールを割り当てると、webロールのサーバーに対してしか処理が行われなくなる。 **設定ファイルの、role、serverの意味ってなに? [#j2801aa6] -cap installで以下のような設定ファイルが作成される。 #pre{{ role :app, %w{deploy@example.com} role :web, %w{deploy@example.com} role :db, %w{deploy@example.com} # Extended Server Syntax # ====================== # This can be used to drop a more detailed server definition into the # server list. The second argument is a, or duck-types, Hash and is # used to set extended properties on the server. server 'example.com', user: 'deploy', roles: %w{web app}, my_property: :my_value }} -コメントによると、roleは、ロールとサーバーの簡易同時設定。serverはサーバーの詳細設定(既存ロール使用)といったイメージか。 *トラブルシューティング [#h9a9b424] **デプロイ後にassetsがプリコンパイルされない [#ce91609e] -Capfileでrequire 'capistrano/rails/assets'が有効になっているかどうか確認する。 **デプロイ後ExecJS and could not find a JavaScript runtimeエラーが発生 [#ta14004a] -[[ruby on rails 3.1 - ExecJS and could not find a JavaScript runtime - Stack Overflow:http://stackoverflow.com/questions/6282307/execjs-and-could-not-find-a-javascript-runtime]]によると、サーバー環境にNode.jsをインストールする。 #pre{{ sudo apt-get install nodejs sudo yum install nodejs }} **デプロイ後「fatal: Not a git repository (or any of the parent directories): .git」と言われてしまう [#e2931787] -Gemfileにローカルフォルダで管理しているgemファイルを追加していて、そのgemspecで以下のようにgitを使っているから。 gem.files = `git ls-files`.split($\) -deploy先に.gitフォルダが存在しないためこのような減少が発生する模様。 -ローカルフォルダでgemを管理するのはやめたほうが良いかもしれない。 -もしくはgemspecでgit ls-filesを使わないようにするか。 [[`git ls-files` in gemspec template is bad practice. · Issue #2287 · bundler/bundler:https://github.com/bundler/bundler/issues/2287]]