アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

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

こんにちは、亀本です。

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

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

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

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

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

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

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

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


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

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

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


そして今回は、Capistranosymfony用レシピを作成し、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


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

3分で使えるRedmine(チケットで課題管理)

こんにちは、岡本です。

プロジェクト管理にRedmineを使っていて、改めて便利だなと思ったので、今更ですが紹介したいと思います。

RedmineRubyで書かれたオープンソースのシステムで、2006年に作られ2007年辺りから日本でも利用され始めた、比較的新しいプロジェクト管理ツールです。

残念ながらPHPでは無いのですが、CakePHPに移植しようと頑張っている方々もいらっしゃいます。
CakePHP開発合宿開始!&candycaneを開発します


さて、Redmineを使えばシステム運用で生じる、不具合や質問・要望等を、チケットという概念でひと括りにして、Web上で管理することができます。

Redmineは元々プロジェクトの工程管理も行える高機能なソフトなのですが、チケットの機能を使って楽をするだけだったら

「3分で使えます。」

トップページ画像

※一部機能をOFFにしています。

学習コストが低くスムーズに導入できるため、アシアル社内でも様々なプロジェクトの課題管理で利用しており、お客様と共同で作業する際にも活用した実績があります。

■実際の運用の流れ
 実際の利用の流れは、お客様やテスター様!がチケットとして不具合や質問項目を【新規】登録し、開発者が泣きながらチケットを【解決】し、問題がなければお客様やテスター様が【終了】するといった流れになります。

チケット作成画面


テスター様:川原様
開発者:岡本

A.「新規」でチケットが発生し、一回の修正で「終了」する場合
ステータスの遷移:新規(川原様)→解決(岡本)→終了(川原様)

終了後のチケット画面


B.「新規」でチケットが発生し、2回目の修正で問題が終了する場合
新規(川原様)→解決(岡本)→フィードバック(川原様)→解決(岡本)→終了(川原様)

C.「新規」でチケットが発生し、却下となった場合
新規(川原様)→却下(岡本)→終了(川原様)


チケットを更新するたびに、お互いにコメントや添付ファイルを残せるため、不具合の起きた画面のキャプチャを張り付けたりして、容易に意思の疎通を図ることが行えます。

■他の仕組みと比較した場合のメリット
メールやメーリングリストと比較した場合
・課題の数や期限を把握しやすい
・ステータス管理で課題の進捗を管理できる
Redmineはチケットが作成・更新された時にメンバー全員にアラートメールが飛ぶため、
メールからの移行も行いやすくなっています。

表計算ソフトとの比較
・Webベースなので情報を複数のメンバーで共有できる
・一つの課題に対してのやり取りを管理しやすい
・ファイルが添付できる

●その他
・課題の管理フローがある程度決まっているので導入に対する学習コストが低い
・自動的に課題に対して管理番号が付く
・更新が簡単に行えるので、情報の鮮度を保ちやすい

■最後に
Redmineガントチャートやカレンダー機能もあり、かなり高機能なプロジェクト管理システムです。
が、チケットの管理だけでも十分利用する価値のあるシステムです。
Redmineの機能をホスティングで提供されるサービス会社様もあるそうなので、システム開発に限らず、制作を行っているデザイン会社様や一般の企業様でも試す価値はあると思います。

Redmine参考リンク
Ruby on Railsで作られたプロジェクト管理ツールredMineを使ってみよう!
gihyo.jp … 技術評論社

RMagickを使ってみた

こんにちは。小川です。

今回はRubyImageMagickを扱うライブラリであるRMagickで遊んでみました。

まずはインストールです。手順はImageMagickをインストールして、RMagickをRubyGemsでインストールします。Ubuntu(Hardy Heron)の場合は以下の通りにやればインストールできるかと思います。



$ sudo apt-get install imagemagick
$ sudo apt-get install libmagick++9-dev
$ sudo gem install rmagick
Building native extensions.  This could take a while...
Successfully installed rmagick-2.5.2


それでは早速使ってみましょう。以下はimage.pngを320x240にリサイズして、image_320x240.pngという名前で保存するスクリプトです。



# ライブラリをロード
require 'rubygems'
require 'RMagick'

# 画像オブジェクトを取得
img = Magick::ImageList.new("image.png")

# サイズを変更する
new_img = img.resize(320, 240)

# 保存
new_img.write("image_320x240.png")


画像をオブジェクトとして扱えるのでとても簡単です。User's Guide and Referenceをみてたら色々あるようなので、コマンドラインで色々変換してくれるスクリプトを書いてみました。



require 'rubygems'
require 'RMagick'

if $0 == __FILE__
  original = ARGV[0]

  unless original
    puts "Usage: ruby #{File.basename(__FILE__)} imagepath"
    exit
  end

  unless FileTest.exists?(original)
    puts "File [%s] not exists" % original
    exit
  end

  # ファイルの読み込み
  img = Magick::ImageList.new(original)
  ext = File.extname(original)

  # 保存用のディレクトリを作成&ディレクトリに移動
  name = File.basename(original, '.*')
  Dir.mkdir(name) unless FileTest.directory?(name)
  Dir.chdir(name)

  # サイズを倍にする
  img.resize(img.columns * 2, img.rows * 2).write("double#{ext}")

  # 色々やってみる
  methods = %w(sepiatone shade sketch vignette flip flop)
  methods.each { |m| img.__send__(m).write("#{m}#{ext}") }
end


これをrmagick.rbとして保存します。では、らーめん大のらーめん野菜増しで実験しましょう。



$ ruby rmagick.rb dai.png


これで完了するとdaiディレクトリができ、その中に色々変換処理をかけられたファイルが入ってると思います。今回は無事成功したので、いくつか紹介したいと思います。







このようにRMagickを使えば簡単に画像の加工ができます。上にリファレンスへのリンクを書きましたが、たくさんのメソッドが用意されてますのでぜひ色々と試してみてください。

問. 配列を+(プラス)演算子で加算すると?

さて問題です。次のようなPHPスクリプトがあります。



<?php
$fruit1 = array('apple', 'banana', 'cherry');
$fruit2 = array('kiwi', 'lemon', 'melon');

$fruit = $fruit1 + $fruit2;
?>


$fruitの値は次のA~Cのどれになるでしょうか?



A. array('apple', 'banana', 'cherry')
B. array('apple', 'banana', 'cherry', 'kiwi', 'lemon', 'melon')
C. array('kiwi', 'lemon', 'melon')


では、早速試してみましょう!



<?php
$fruit1 = array('apple', 'banana', 'cherry');
$fruit2 = array('kiwi', 'lemon', 'melon');

print_r($fruit1 + $fruit2);
?>




Array
(
    [0] => apple
    [1] => banana
    [2] => cherry
)


というわけで、正解は「A」です!

如何だったでしょうか。皆さんの思っていた通りの結果になりましたでしょうか?

ちなみに、私はてっきり「B」になるものと思ってました……。なお、



$fruit = array_merge($fruit1, $fruit2);


であれば「B」になります。

ググってみたら、以前のPHPプロ!のTIPSでも「配列の + (プラス) 演算子」として取り上げられてますね...orz

個人的にはあまり直感的な動きではないように思えるので、他の言語ではどうなんだろうと、ちょっと試してみました。

Python


fruit1 = ['apple', 'banana', 'cherry']
fruit2 = ['kiwi', 'lemon', 'melon']

print fruit1 + fruit2




['apple', 'banana', 'cherry', 'kiwi', 'lemon', 'melon']


Ruby


fruit1 = ["apple", "banana", "cherry"]
fruit2 = ["kiwi", "lemon", "melon"]

p fruit1 + fruit2




["apple", "banana", "cherry", "kiwi", "lemon", "melon"]


んー、PHPだけ違いますね。

なぜPHPではこういった実装になっているのかはわからないのですが、array_merge()よりも+演算子の動作のほうが便利な場合もありますので、動作の違いをきちんと把握して使いこなしたいところですね。

このように言語によって実装が異なりますので、配列の結合を「+」演算子で行う際はみなさんもご注意くださいませ。