LoginSignup
161
151

More than 5 years have passed since last update.

Capistrano3の動作まとめ。

Last updated at Posted at 2015-11-09

はじめに

Capistrano3を使ったデプロイ手順をまとめます。

このまとめは僕がCapistranoの詳細について知りたいと思ってまとめたものになります。
この文献を読めばCapistranoに対する理解は深まると思いますが、使用する際に知らなくても良い情報も多数記載されています。
(使い方だけを知りたい方は「デプロイレシピの書き方」から読んでください。)

はじめはRailsデプロイに特化した記事にしようと思ったのですが、Capistranoに関する仕様が多くこの記事だけでは収まらなかったため本記事はCapistrano全般に関する記事に変更しました。
なので、PHPやJavaなどのデプロイで使う場合にも参考になる記事になってます。

※僕が調べた限りの情報なので間違っている部分やあやふやな部分もありますので怪しいと思ったところに関してはご指摘いただければと思います。

インストール

インストールするディレクトリを適当に作成して以下のファイルを作成します。
(あらかじめRubyのインストールは済ませておいてください。またgem install bundleの実施も事前に行っておいてください。)

Gemfile
source 'https://rubygems.org'

gem 'capistrano'

Gemfileを作成したディレクトリで

$ bundle install

を行う。

その後

$ bundle exec cap install

と行う。

特に何も指定しない場合は「staging」と「production」用の設定ファイルが作成される。
あとで追加もできるが、初めに作って欲しい設定ファイルがある場合は以下の様に設定することも可能。

$ bundle exec cap install STAGES=development,staging,production

STAGESパラメータをつけることで初めのファイルを指定できます。
(といっても、ファイルを作成/削除すればいいだけの問題なので無理に覚えておく必要はありません。)

ディレクトリ構成

作成された後のディレクトリは以下の構成になってます。

パス 説明
Capfile capistranoが実行される際に読み込むgemファイルやtaskを記載します。
config/deploy.rb capistranoが実施するレシピを記載します。
config/deploy/**.rb 各環境ごとの設定を記載します。※上記で指定したSTAGESのファイルが作成されます。
lib/capistrano/tasks/ capistranoに実施させたいタスクを定義します。(本記事では扱いません。)

Capistranoのおおまかな流れ

Capistranoは以下の流れでデプロイを行います。

基底ディレクトリの作成

Capistranoは以下のディレクトリ構成でデプロイを行います。

current・・・releasesに入っている最新のディレクトリに対するシンボリックリンク
releases
∟20151105121212・・・YYYYmmddHHMMSS形式でリリースプログラムが複数配置される。
∟YYYYmmddHHMMSS
shared・・・releasesに依存せず、共通となるファイルが配置される。

Capistranoはデプロイするたびにreleasesのディレクトリの中にデプロイした日時のディレクトリを作成して、その中にSCM(gitやsvn等)で取得したファイルを配置している。(詳細は後述)
その配置したディレクトリの一番新しい日時のディレクトリに対してcurrentからシンボリックリンクが張られる。

なのでPassengerunicornを使う場合はcurrentに対してパスを通せば動く仕組みである。(unicornの場合はソケット)

なぜこんな構成になっているか?

rsyncなどでデプロイをした方なら上記の構成に疑問を持つかもしれない。

rsyncなどの手動デプロイをする場合はcurrentだけ作成して中身のファイルを置き換えていく手順が多い。
その方法だと誤ったファイルをデプロイしてしまうと元に戻すのが大変だったり、場合によっては元に戻せないという悲劇が産まれるかもしれない。

releasesに毎回ディレクトリを切ることでこの状況をある程度回避できる。(DBの変更などがあると回避できない場合がある。)
すなわち、デプロイしたものにバグがあったりして前のバージョンに戻したい場合はcurrentのシンボリックリンクを一つ前のreleasesに貼り直せば元に戻るという仕組みである。(Capistranoにはこれを行うためにrollbackと言うタスクが用意されている。)

ちなみにこの方法だとreleasesディレクトリが肥大化するが、keep_releasesと言う設定(デフォルトは5)を記載しておけば指定の個数以上の日時ディレクトリができた場合は古いものから消していってくれる。

デプロイ方法

Capistranoは以下の手順でデプロイを行う。

  1. 各サーバーに上記の構成ファイルを作成する。
  2. 各サーバー上でSCMからデータを取得する。(/tmp/APPLICATION_NAME/*git clone --mirrorでデータを取得する。)
  3. 取得したファイルを各サーバーのreleasesディレクトリに展開する。
  4. 各サーバーでcurrentのシンボリックリンクをreleasesの最新ディレクトリに張り替える。

おおまかにこの手順でデプロイを行う。
そのため、Railsに関わらずPHPなどの他のプロジェクトにも適用できる。

Railsをデプロイする場合はもう少し複雑な手順が必要。それらに関しては別途記事を書きます。

おまけ

Capistrano2の時代では作業PCにgit cloneしてgzipで固めて各サーバーに配置してた気がするけど、、、最近はそういう方法は使わないんですね。

Capfile(基底タスクの確認)

このままでも使用できますが、Capfileの中身を知らないで使用するのは怖いという方は以下を読んでください。

このファイルにrequireしていくと使えるタスクが増えて行く。
requireしたいgemに関しては上記のGemfileに記載してあらかじめbundle installをしておく。

require 'capistrano/setup'

Capistranoの基底処理が記載されている。
デプロイするディレクトリなどの作成を行っている。

setup.rb
include Capistrano::DSL

namespace :load do
  task :defaults do
    load 'capistrano/defaults.rb'
  end
end

stages.each do |stage|
  Rake::Task.define_task(stage) do
    set(:stage, stage.to_sym)

    invoke 'load:defaults'
    load deploy_config_path
    load stage_config_path.join("#{stage}.rb")
    load "capistrano/#{fetch(:scm)}.rb"
    I18n.locale = fetch(:locale, :en)
    configure_backend
  end
end

require 'capistrano/dotfile'

この処理はこの後に必要となるRubyファイルを読み込んでいる。
Capistranoを使う上で重要なのはload 'capistrano/defaults.rb'の部分になる。

set_if_empty :scm, :git
set_if_empty :branch, :master
set_if_empty :deploy_to, -> { "/var/www/#{fetch(:application)}" }
set_if_empty :tmp_dir, "/tmp"

set_if_empty :default_env, {}
set_if_empty :keep_releases, 5

set_if_empty :format, :pretty
set_if_empty :log_level, :debug

set_if_empty :pty, false

set_if_empty :local_user, -> { Etc.getlogin }

このように何も指定してない場合のデフォルトが定義されている。
この後に書かれているコードを見れると、上記のcapistrano/defaults.rbを読み込んだ後にconfig/deploy.rbを読み込みその後にconfig/deploy/**.rbを読み込んでいる事がわかる。

invoke 'load:defaults'
load deploy_config_path
load stage_config_path.join("#{stage}.rb")

すなわちconfig/deploy.rbconfig/deploy/**.rbに定義されていないパラメータは上記が使われるのだ。
また、config/deploy/**.rbが最後に定義されているのでconfig/deploy/**.rbに設定した内容が一番強い事がわかる。

これはdeploy.rbに書いたレシピの設定を各環境(config/deploy/staging.rbconfig/deploy/production.rb)で上書きできる事を指している。

stagedeploy_toなどのデフォルト設定をdeploy.rbに書いておき、各環境ごとで変化する場合は変えれるという事だ。

おまけ

stages.eachconfig/deploy/**.rbのファイル全てが対象となる。
すなわちcapistranoはstagingにデプロイするときにもproductionのデータも読み込んでいるようだ。(他のstageのファイルは使われないはずだが・・・)

require 'capistrano/deploy'

Capistranoをデプロイするためのタスクと順番が定義されている。
内部でrequireされている'capistrano/framework'にタスクの順番が定義されいてる。

namespace :deploy do
  task :starting
  task :started
  task :updating
  task :updated
  task :reverting
  task :reverted
  task :publishing
  task :published
  task :finishing
  task :finishing_rollback
  task :finished
  task :rollback
end

中身のタスクだけ抜き出すとこんな感じだ。
そして肝心のdeployタスクは以下のように記載されている。

desc 'Deploy a new release.'
task :deploy do
  set(:deploying, true)
  %w{ starting started
      updating updated
      publishing published
      finishing finished }.each do |task|
    invoke "deploy:#{task}"
  end
end
task default: :deploy

この設定で各タスクを順番通り呼び出している。
なお、rollbackには以下のように記載されている。

%w{ starting started
    reverting reverted
    publishing published
    finishing_rollback finished }.each do |task|
  invoke "deploy:#{task}"
end

微妙に中身が違う事がわかると思う。

各タスクの説明(../tasks/deploy.rake)

Capistranoを使う上で重要となるタスクの中身がここに定義されている。
ただ、これらを細かく追うと長くなるので僕が読んで理解した範囲で記載する。

なお、Capistranoのdeploy.rakeは全てのサーバーに対して行われる。

starting(デプロイ、ロールバック共に呼び出される。)

Capistranoで一番初めに呼ばれるタスクだ。
中には以下のように記載されている。

invoke 'deploy:check'
invoke 'deploy:set_previous_revision'

簡単に流れを書くと以下のような感じになる。

  1. git ls-remote --headsで更新を確認.
  2. execute :mkdir, '-p', shared_path, releases_pathでCapistranoが使用するディレクトリを作成する。
  3. execute :mkdir, '-p', linked_dirs(shared_path)で指定されているディレクトリのリンボリックリンクを作成する。
  4. execute :ln, '-s', source, targetで指定されているファイルのシンボリックリンクを作成する。
  5. previous_revisionを作成する。(各タスク内でprevious_revisionが使用できるようになる。)

※ロールバックでもこのタスクが呼び出されるという事は、ロールバック時にcheck用としてgitへのアクセスが発生しているという事である。

started(デプロイ、ロールバック共に呼び出される。)

deploy.rake内では特に処理をしていない。
各レシピ内で必要に応じて初期用のタスクを作成する。

updating(デプロイのみ)

アップデートタスクは以下のように記述されている。
これが実際にファイルを各サーバーに対してアップデートをかけている。

task :updating => :new_release_path do
    invoke "#{scm}:create_release"
    invoke "deploy:set_current_revision"
    invoke 'deploy:symlink:shared'
end

:updating => :new_release_pathの部分はupdatingタスクを行う前にnew_release_pathが行われる事を示してます。
(後述しますがbefore : updating, :new_release_pathと同義です。)
new_release_pathでは以下の処理が行われてます。

set(:release_timestamp, timestamp)
set(:release_path, releases_path.join(timestamp))

ここではまだリリースフォルダを作成せずに、リリースする情報を設定してます。

#{scm}:create_release

ここの部分は肝となるので詳細を追っていきます。
gitの場合は以下のようにタスクが定義されています。

namespace :git do

  def strategy
    @strategy ||= Capistrano::Git.new(self, fetch(:git_strategy, Capistrano::Git::DefaultStrategy))
  end

  set :git_environmental_variables, ->() {
    {
      git_askpass: "/bin/echo",
      git_ssh:     "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh"
    }
  }

  desc 'Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt'
  task :wrapper do
    on release_roles :all do
      execute :mkdir, "-p", "#{fetch(:tmp_dir)}/#{fetch(:application)}/"
      upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh"
      execute :chmod, "+x", "#{fetch(:tmp_dir)}/#{fetch(:application)}/git-ssh.sh"
    end
  end

  desc 'Check that the repository is reachable'
  task check: :'git:wrapper' do
    fetch(:branch)
    on release_roles :all do
      with fetch(:git_environmental_variables) do
        strategy.check
      end
    end
  end

  desc 'Clone the repo to the cache'
  task clone: :'git:wrapper' do
    on release_roles :all do
      if strategy.test
        info t(:mirror_exists, at: repo_path)
      else
        within deploy_path do
          with fetch(:git_environmental_variables) do
            strategy.clone
          end
        end
      end
    end
  end

  desc 'Update the repo mirror to reflect the origin state'
  task update: :'git:clone' do
    on release_roles :all do
      within repo_path do
        with fetch(:git_environmental_variables) do
          strategy.update
        end
      end
    end
  end

  desc 'Copy repo to releases'
  task create_release: :'git:update' do
    on release_roles :all do
      with fetch(:git_environmental_variables) do
        within repo_path do
          execute :mkdir, '-p', release_path
          strategy.release
        end
      end
    end
  end

  desc 'Determine the revision that will be deployed'
  task :set_current_revision do
    on release_roles :all do
      within repo_path do
        with fetch(:git_environmental_variables) do
          set :current_revision, strategy.fetch_revision
        end
      end
    end
  end
end

release_roles :allと定義されているので、他と同様で全てのサーバーが対象になります。
タスクの順番を整理すると以下の順番に実行されている事がわかります。

task :wrapper
task :clone
task :update

大まかですが、以下の処理をしている事がわかります。

  1. テンポラリー領域にGitを実施するためのディレクリや実行ファイルを作成します。
  2. git :clone, '--mirror', repo_url, repo_pathを行ってgitからデータを取得します。
  3. git :remote, :updateを行う。
  4. execute :mkdir, '-p', release_pathでリリースディレクトリを作成します。
  5. git :archive, fetch(:branch), '| tar -x -f - -C', release_pathでgitから取得したファイルをリリースディレクトリに展開する。

なお、1番で取得している実行ファイルは以下のようなファイルになります。

#!/bin/sh -e
exec /usr/bin/ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no "$@"
"#{scm}:set_current_revision"

SCMからデータを取得した後に最新のリビジョンを取得してコンソールに表示します。

context.capture(:git, "rev-list --max-count=1 --abbrev-commit #{fetch(:branch)}")
シンボリックリンク

最後にシンボリックリンクの指定があればsharedへシンボリックリンクを張ります。

updated(デプロイのみ)

deploy.rake内では特に処理をしていない。
各レシピ内で必要に応じて配置後用のタスクを作成する。
(この時点ではまだ本番適用はされていない。)

publishing(デプロイ、ロールバック共に呼び出される。)

currentからreleaseにシンボリックリンクを貼り直します。
実際には一時的にtmp_current_pathを作成して、そこからreleaseへシンボリックリンクを張ってからcurrentmvします。

おまけ

Capistranoでデプロイ中にcurrentディレクトリに移動して、デプロイ後にlsなどのコマンドを叩くと何もない状況に陥るのはこのためである。

published(デプロイ、ロールバック共に呼び出される。)

deploy.rake内では特に処理をしていない。
各レシピ内で必要に応じてデプロイ後用のタスクを作成する。
(この時点ではすでに本番適用されている。)

finishing(デプロイのみ)

リリースディレクトリの数を数えて指定の数より多い場合は、古いディレクトリを削除します。

finished(デプロイのみ、ロールバック共に呼び出される。)

revision_log_messageを出力して終わります。

以下はロールバック時に発生するタスクです。

reverting(ロールバックのみ)

updatingではreleases_pathに新しい日時のディレクトリ名を設定してましたが、ロールバック時は一つ古いリリースディレクトリ名を設定します。
これにより後続で走るpublishingcurrentの付け替えが古いものになります。
revision_log_messageを設定します。(finishingで出力されます。)

reverted(ロールバックのみ)

deploy.rake内では特に処理をしていない。
各レシピ内で必要に応じてロールバック後用のタスクを作成する。
(この時点ではすでに本番適用されている。)

finishing_rollback(ロールバックのみ)

ロールバックしたため一番新しいリリースディレクトリを使用しなくなりました。
その不要ディレクトリを削除します。

Capistranoの実行手順まとめ

文字だけでは伝わりにくいと思うので、簡単に説明します。

デプロイ時

初めのデプロイで以下の状態が発生します。

current
releases
∟1・・・本来はYYYYmmddHHMMSS型で作成されるが、説明の便宜上1番目にできるディレクトリとする。
shared

シンボリックリンクは以下のようになっています。
(最近のRailsではdatabase.ymlにシンボリックリンクを張る必要はないが、説明上以下のようなシンボリックリンクが張られているとします。)

current -> releases/1
releases
∟1
 ∟database.yml -> shared/database.yml
shared
∟database.yml

こちらに対して再度デプロイを行うと以下のようになります。

current -> releases/2
releases
∟2
 ∟database.yml -> shared/database.yml
∟1
 ∟database.yml -> shared/database.yml
shared
∟database.yml

このようにreleases配下にデプロイされたモジュールが出来てきます。

ロールバック時

上記の状態に対してロールバックを行うと以下のようになります。

current -> releases/1
releases
∟1
 ∟database.yml -> shared/database.yml
shared
∟database.yml

見てわかる通り、最後にリリースされたreleases/2が消えて一回目のデプロイと同じ状況に戻ります。
(この状態でロールバックを行うと途中で処理が停止します。)

デプロイ時エラーの場合

上記の状態に対してデプロイをしている途中の状態は以下のようになります。

current -> releases/1
releases
∟2
 ∟database.yml -> shared/database.yml
∟1
 ∟database.yml -> shared/database.yml
shared
∟database.yml

この状態でエラーを感知するとCapistranoはロールバックを発生させます。
(どうやってロールバックを発生させているのかは、コード上からは追いきれなかった・・・。)

current -> releases/1
releases
∟1
 ∟database.yml -> shared/database.yml
shared
∟database.yml

そのため、デプロイ時に予定外の事が発生してもある程度はカバーされます。
データベースに変更を加えたりした場合はrevertingタスクの前後に対応コードを入れる必要がある。

デプロイレシピの書き方

とりあえず使いたいという方はここから読んでください。
長々書きましたが、使い方はある程度シンプルです。
(デプロイシェルを書くよりは遥かにシンプルになります。)

タスクの作成方法

config/deploy.rb
namespace :test do
    task :task1 do
        p "call task1"
    end
end

基本的な記述は上記のようになります。
上記のコードをconfig/deploy.rbの最後に追加してください。
そして以下のコマンドを叩いてください。

$ bundle exec cap staging test:task1

これでタスクが実行されてcall task1と表示されたと思います。
実際はこのような使い方はしませんが、実行されるルールの例として書いてます。

各サーバーで実行する方法

Capistranoはデプロイ対象のサーバー上でコマンドを打つ必要があります。
その対象のサーバーで実行するためには以下のように行います。

まずはサーバーの設定を行います。
(通常はconfig/deploy/**.rbに記載します。)

例えば本番サーバーの設定を以下のようにしたとします。

config/deploy/production.rb
server '172.1.1.1', user: 'user', roles: %w{web app batch}
server '172.1.1.2', user: 'user', roles: %w{web app}

ステージングサーバーが2台あったとします。
そのうち一台はバッチサーバーも兼用してたとします。
(本説明ではuserは割愛しますが、上記で指定しているユーザーはsshコマンドを実行するユーザーです。)

config/deploy.rb
namespace :test do
    task :task1 do
        on roles(:app) do
            execute 'echo "app server!"'
        end
    end

    task :task2 do
        on roles(:batch) do
            execute 'echo "batch server!"'
        end
    end
end

このように記述して実行します。
config/deploy/production.rbの内容で実行する場合はcap production **と記述します。)

$ bundle exec cap production test:task1
$ bundle exec cap production test:task2

test:task1は両方サーバー上で'echo "app server!"'のコマンドを実行します。
test:task2172.1.1.1サーバー上で'echo "batch server!"'のコマンドを実行します。

このようにon rolesという記述を使うと実施させるサーバーを指定させることができます。

絶対に一台のサーバーだけで実施したい場合

上記の設定ファイルが以下のようになっていたらどうなるでしょうか?

config/deploy/production.rb
server '172.1.1.1', user: 'user', roles: %w{web app batch}
server '172.1.1.2', user: 'user', roles: %w{web app}
server '172.1.1.3', user: 'user', roles: %w{web app batch}

この状態で先ほどのタスクを実施するとrolesbatchのサーバーが二つ存在するため二つのサーバーで実施されてしまいます。

通常はこのような設定を行うときは意図的なので問題が出ることはありません。
しかし、念のため対応したいという場合は以下のような記述ができます。

config/deploy.rb
namespace :test do
    task :task3 do
        on primary(:batch) do
            execute 'echo "only one batch server!"'
        end
    end
end

このように記述した場合は先に見つかったbatchロールでのみ実施されます。

設定値を使いたい場合

レシピ内に設定値を記載すると後で変更するときに苦労します。
Capsitranoでは以下の方法で値を設定できます。

config/deploy.rb
set :message, "hello world!"
namespace :test do
    task :task1 do
        on primary(:app) do
            execute 'echo "#{fetch(:message)} batch server!"'
        end
    end
end

set :message, "hello world!"messagehello world!を設定します。
fetch(:message)で実際の値を取得します。
他の文法に関してはRubyの文献通りです。

なお、設定値がない場合にfetchするとnilが返却されます。
もし設定値がない場合にはデフォルト値を使いたい場合はfetch(:message, "ここに書く")のように記述できます。

config/deploy.rb
namespace :test do
    task :task1 do
        on primary(:app) do
            execute 'echo "#{fetch(:message, "not message!!")} batch server!"'
        end
    end
end

設定値の上書きしたい場合

fetch(:message, "ここに書く")を使うと分かりにくいので、config/deploy.rbに規定の値を書いてconfig/deploy/**.rbで上書きしたいと言うこともできます。

Capistranoではconfig/deploy.rbconfig/deploy/**.rbの順番にファイルをロードするので同じ設定を書いた場合はconfig/deploy/**.rbに記述した内容で上書きされます。

実行時に設定値を設定したい場合

実行するたびに設定値を変更したい場合は以下のように記述します。

config/deploy.rb
set :message, ask("what message?", "hello world")
namespace :test do
    task :task1 do
        on primary(:app) do
            execute 'echo "#{fetch(:message)} batch server!"'
        end
    end
end

これを実行すると以下のようになります。

$ bundle exec cap production test:task1
Please enter What message? (hello world):

入力した値が表示されることが確認できます。

実行するコマンドに引数を追加したい場合

例えばRailsのコマンドを実行する際に環境引数であるrails_envを引き渡したい場合は以下のように行います。

set :rails_env, :staging
with rails_env: fetch(:rails_env) do
    execute :rake, "db:create"
end

このように記述すると以下のコマンドが指定されたロールのサーバーで実行されます。

$ RAILS_ENV=staging bundle exec rake db:create

実行する前にフォルダ/ファイルの確認をしたい場合

フォルダが存在した場合のみ実行する場合は以下のように行います。

within current_path do
    # カレントパスがある場合のみ実行される。
end

ファイルを確認する場合

if test "[ ! -e #{shared_path}/.env ]"
    # shared/.envが存在しない場合に実施する。
end

こちらが参考になります。
【 test 】 条件式の真偽を判定する

サーバーへファイルをアップロードしたい。

デプロイで管理されているSCM以外でファイルをアップロードしたい場合は以下のように行います。
(個別タスクとして切り出して、デプロイとは別のタイミングで行う場合が多いので以下のようなタスクになると思います。)

task :upload_file do
    on roles(:app) do |host|
        if test "[ ! -e #{shared_path}/.env ]"
            upload!('../.env.example', "#{shared_path}/.env") # .env
            execute 'echo ".env uploaded!"'
        end
    end
end

この例では、Railsの環境ファイルである.envappサーバーへアップしてます。

タスクの途中にタスクを追加したい

タスクの途中にタスクを追加するためにはbeforeafterコマンドを使用します。

task :task1 do
    execute 'echo "execte task1!"'
end
task :task1_1 do
    execute 'echo "execte task1_1!"'
end

というタスクがあるときに以下のように定義すると

before :task1, :task1_1

task1を実行すると以下のように表示されます。

$ cap *** task1
execte task1_1!
execte task1!

また、上記のタスクに対してafterを使うと以下のようになります。

after :task1, :task1_1
$ cap *** task1
execte task1!
execte task1_1!

実際にデプロイに組み込みたい

実際にデプロイに組み込む場合は以下のようになると思います。
Railsを例に記載してますが、タスクの中身は各環境に合わせて変更してください。

namespace :deploy do
  # 個別タスクを定義する場合。以下のコマンドで実行
  # $ cap *** deploy:db_seed
  # もちろん、毎回実行させても良い。
  desc 'db_seed must be run only one time right after the first deploy'
  task :db_seed do
    on roles(:db) do |host|
      within current_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, 'db:seed'
        end
      end
    end
  end

  # ファイルをアップロードされる前にタスクを挿入する場合。
  # ※この例ではdatabseを作成している。
  # on rolesよりon primaryの方が適切かもしれない。
  before :updated, 'db_create'
  task :db_create do
    on roles(:db) do
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, "db:create"
        end
      end
    end
  end

  # 実際にデプロイが完了した後に処理を行う場合。
  after :publishing, :restart
  desc 'Restart application'
  task :restart do
    on roles(:app) do
        # 例えばUnicornを再起動させる。
      invoke 'unicorn:restart'
    end
  end
end

このように定義して

$ cap *** deploy

と実行すると、デプロイ処理と上記に記載したタスクが実行されます。

設定する内容

なお、事前に設定する内容で必須なのは以下になります。

set :application, 'application_name' # application名はなんでも良い。
set :repo_url, 'git@gitpub.****.git' # デプロイ対象のリポジトリ
set :branch,  'master' # ブランチの指定をしたい場合はここに記載。

上記にも記載した通りでconfig/deploy/***.rbに記載すれば上書きできます。

失敗した場合は?

デプロイ中にいずれかのサーバーの一つでも失敗が発生した場合は、すべてのサーバーに対してロールバックが発生します。

一つのサーバーだけ処理が成功するという事はありません。

Capistrano2との違い。

deploy:setupが無くなりました。
記述方法が変わったので、そのままでは使用できません。
Railsに特化してたCapistrano2とは違い、上記のようにCapistrano3では他の環境でも使えるように汎用的なものになってます。

161
151
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
161
151