symfonyアプリケーションをデプロイするためのCapistranoレシピ

こんにちは、亀本です。

1週間ぶりです。というのも、今までご無沙汰過ぎて、ブログ当番に2週連続であたってしまいました。
やっぱり普段からコツコツやっとかないとだめですね。反省反省。

さて、今回はデプロイのお話です。
アプリケーションのデプロイといえばリリースの締めの一番ミスできないところです。
みなさん、これをどうやって作業していますか?

最近はバージョン管理システムが導入されるのが当たり前になっている場合が多く、リポジトリからのチェックアウトで済ませてしまうとか、rsyncするだけという方も多いんじゃないでしょうか。

もちろん、Webサーバ2~3台ぐらいだったらそれで事足りますし、適切なポリシーを持って臨めば、セキュリティ的に問題が発生するような事態にも陥らないでしょう。

しかし、バージョン管理システム自体やrsyncを使ったデプロイは手軽であるというメリットの裏で、以下のような不安材料も抱えています。

・ロールバックの概念がない(障害発生時にすぐ戻せない)
・デプロイサーバからの指示だけで作業を完結できない(本番サーバに手を入れる必要がある)
・更新後にApacheの再起動など、複数の作業を並列実行できない
・複数台の場合、最初のデプロイと最後のデプロイで時間差が出る

これらの点は管理台数が増えれば増えるほど、大きな問題として頭をもたげてきます。
それこそ、2~3台レベルの時には手動で対応できた内容が、台数が増えるだけでとんでもない作業量になったりします。
こういった問題を解決するためには、何かしら作業を前サーバに対して適用してくれるシェルスクリプトなり、サポートツールが必要になってきます。

こういった問題に対して、自分も最初はシェルスクリプトを使って、rsyncをラッピングしてロールバック可能な構成でデプロイしてくれるような仕組みを作ったんですが、さらに一括ロールバックのギミックやメンテナンスモード切り替え、などといった機能をいくつも実装しなければならないのは結構骨だなぁと思っていました。
やっぱり、便利なデプロイツールはほしくなるものです。

そして、そんなツールとして特に注目度が高いのがCapistranoです。
CapistranoはRubyで作られたRails向けのデプロイ管理ツールで、

・リリースのバージョン管理
・複数台デプロイ
・複数タスクの自動実行
・ロールバック処理
・メンテナンスモード切替

などを備えています。
デプロイ機能がデフォルトでRails専用になっているとはいえ、タスクの追加も容易で、レシピと呼ばれるタスク定義・設定ファイルにちょっと手を加えれば、Rails以外のシステムにも簡単に応用が利く優れものです。

そして今回は、Capistranoのsymfony用レシピを作成し、symfonyのデプロイに対応させてみました。
# そんな話をIRCでしてたら、もうやってる人いたけど、そこは気にしたら負けということで(^^;

このレシピファイルはgithubにアップしておきましたので、ご自由にお使いください。
ほぼかき捨てですが、一応、MITライセンスという感じで。(ライセンスよくわかってないので)

http://github.com/yudoufu/symfony-capistrano-recipe

ちなみに人生で初めて.rbを編集しました。rubyとかよくわかりません。rubyわかる人誰かきれいにしてください。
って、rubyというほどruby書いてませんが。

基本的な使い方は、任意のディレクトリに上記のレシピをcloneしてきて、必要な設定を書いたら


% cap deploy:setup
% cap deploy:install

とすれば、プロジェクトの配置が完了します。
その後、プロジェクトのファイル群を更新するには、


% cap deploy

とすれば、symfony本体とpluginsを除く、プロジェクトのファイル群を更新してくれます。
普段のリリース作業は、ほぼこれだけになると思います。

ざっと基本的な使い方を説明したところで、Capistranoのインストールからの利用手順と、各タスクの紹介を順にしていきます。

なお、Capistorano自体の基本的な説明は
http://www.oiax.jp/rails/capistrano.html
http://builder.japan.zdnet.com/sp/open-source-software-moonlinx-2009/story/0,3800096543,20396188,00.htm
といったあたりをご覧ください。
一度どちらかでも目を通しておいて貰ったほうが、全体の理解が進むと思います。

では、ひとまずCapistrano自体の説明は上記のサイトを読んでもらうとして、準備手順だけかっ飛ばして説明していきます。

1. Capistranoのインストール

rubygemsは、必須です。
そのあたりはyumやaptなんかで入れておいてください。


% sudo gem install capistorano
% sudo gem install capistorano_colors

後者は任意で。
Capistranoをインストールすると、cap と capifyという2つのコマンドが使えるようになります。

2. レシピのclone

githubから上記のレシピファイルを取得してきます。


% git clone git://github.com/yudoufu/symfony-capistrano-recipe.git

とりあえずここで、ファイルの内訳を簡単に。


symfony-capistrano-recipe
  /Capfile
  /config
      /deploy.rb
      /symfony.rb
  /uploads/config/databases.yml

Capfileは言わずと知れた、といったところです。ちょっと標準のものから手を加えてありますが、アンタッチャブルです。
deploy.rbでは、諸々の設定を行います。基本的に、普段はこいつを編集してもらうことになります。
symfony.rbが、主に今回作成したレシピです。こいつを見てもらえれば、大体何をやっているかがわかります。通常はアンタッチャブルです。

そして、uploadsディレクトリですが、ここにはプロジェクトディレクトリにアップロードしたい設定ファイルなどを配置します。
普通、databases.yml等のファイルはバージョン管理システムのリポジトリには含めず、各サーバごとに管理していると思います。
そういった、リポジトリに含まれていないけどデプロイ時に配置されてほしいファイル群を、このuploadsディレクトリの中に置いて、ファイル名をdeploy.rbで指定すれば、デプロイ実行時にそれらのファイルも合わせてアップロードされます。

ここでは、デフォルトでconfig/databases.ymlだけ置いてありますが、これを適宜編集したり、必要なファイルを追加で配置していってください。

3. deploy.rbの編集

あとは、必要な変数を自身の変数に変更すれば、デプロイの準備は完了です。
大体どこに何を。。。というのは、ファイルのコメントを読んでもらえればわかると思います。
以下にファイルを張りつけておきます。

4. タスクの実行

というわけで、後はタスクを実行するだけです。
基本的なタスクの説明はさっきしたので、ここでは、もう少し個別に色々掘り下げます。

4.1. setup


% cap deply:setup

これはCapistranoがもともと持っているタスクで、上記のURLなどで説明されているように、リリース準備としてデプロイ先のディレクトリを生成してくれます。
通常、まず最初はこれをやります。

ここで出来上がるディレクトリ構成は


{deploy_to}
    /release
    /shared
        /log
        /web/uploads
        /plugins
        /lib/vendor/symfony

といった構成で出来上がります。
詳細の説明は上記のCapistranoの記事に譲りますが、sharedの中が全リリース共通で使うもの、releaseのなかが毎回変わるプロジェクト系のファイルが格納される場所です。

なお、sharedの中に作られるディレクトリは、それぞれshared_children、plugins_dir、symfony_lib_dirの設定をsetすることで指定できます。
どれがどう設定されているかは、コード見てもらえればわかると思います。

4.2. install


% cap deploy:install

symfonyのプロジェクトを丸ごとチェックアウトしてきて、適切に配置してくれます。
一番最初に配置を行う際に利用されることを想定しているタスクです。
(setupも同時に実行するようにしてもよかったんですが、気分的に分けました)

このタスクは
・symfonyのプロジェクト全体(externals指定のものもすべて)をチェックアウト
・sharedにsymfony本体を配置
・sharedにpluginsのファイル群を配置
・releaseにプロジェクトの各種ファイル群を設置
・デプロイ元のuploadsディレクトリに配置したファイル群を、releaseディレクトリに自動配置
・symfony cc
・currentディレクトリに対して、シンボリックリンクを作成
・startタスクの実行(Apacheの起動を割り当てたりします)

というのを、一気にやってくれます。
Apacheの設定などが済んでいれば、これで一気にデプロイが完了できます。

4.3. default


% cap deploy

先ほども紹介したデフォルト実行タスクで、

・プロジェクトリポジトリのファイルのみをチェックアウト(--ignore-externals)
・releaseにプロジェクトの各種ファイル群を設置
・デプロイ元のuploadsディレクトリに配置したファイル群を、releaseディレクトリに自動配置
・symfony cc
・currentディレクトリに対して、シンボリックリンクを作成
・restartタスクの実行(Apacheの起動を割り当てたりします)

というのを一通りやってくれます。

symfonyはそれ自体がかなりでかいフレームワークなので、チェックアウトにも時間がかかるし、tarで固めるにしても複数台にデプロイするにはかなりの転送量になります。
なので、symfonyはpluginsといった、基本的にsvn:externalsで扱われるようなものはshared扱いにし、普段はチェックアウトを行わずにプロジェクト単体だけの取得・転送にとどめることで、いろんな負荷を軽くしてます。
通常、リリース時にはsymfonyのバージョンはFIX、pluginsも同様に扱われることがほとんどだと思うので、これらをsharedで扱っても十分です。

4.4. upgrade

symfonyは更新しないけどpluginsに追加/更新があった、なんて場合には


% cap deploy:upgrade

とすると、defaultのタスクに加え、プロジェクトのファイルだけでなくpluginsの中身も最新化してくれます。

4.5. dist_upgrade

さらに、めったにないと思いますが、セキュリティFIXなどがあってsymfony自体も新しいバージョンに切り替えた!なんていう場合には


% cap deploy:dist_upgrade

とすると、symfony、plugins、プロジェクトファイル群のすべてを更新してくれます。
やっている事はほとんど4.2. installと同じですが、最後にrestartタスクが実行される点だけが違います。

4.6. uploads

設定ファイル群の更新のみを行いたい、という場合には、


% cap deploy:uplods

を使うと、uploadsディレクトリの中のファイルアップロード+symfony cc だけに特化して処理を行ってくれます。
大掛かりな作業にならずに済むので、結構色々使えると思います。

4.7. cc

いわゆるsymfony ccをかけたいときには


% cap deploy:cc</strong>

とします。
これで、各サーバのcurrentのディレクトリでsymfony ccが実行されます。

※なお、migrateも一応実装してありますが、railsのmigrateとsymfony/doctrineのmigrateではちょっと意味合いが違うため、これはあんまり適切なタスクになっていないかもしれません。
なので、説明は割愛しますので、使いたい人はコード読んでください。
(その関連で、coldタスクもあまり使い勝手の良いものにはなっていないと思います。)

以上が、一通りの機能説明です。

多分、複数台デプロイに必要なタスクはこれで一通りは使えるのではないかと思いますが、折があれば便利な機能を色々追加していきたいと思います。
要望などあれば、どしどしコメントください。
# もちろんコミットも大歓迎ですw

では、皆様にストレスフリーなデプロイ・ライフを。