CakePHPのデプロイ
svn, rsync, lftpを使ったデプロイ
開発環境はWindows、テストサーバーはCentOS、本番サーバーはFreeBSD。
CakePHP1.2、開発環境とテストサーバーはDB共用で、本番サーバーのDBはlocalhostという環境。
バージョン管理はSubversion(Trac)を利用。
本番サーバーはFTPでしかアクセスできない。
今まではテストサーバーにsvn exportしてapp/tmp を777にするスクリプトを作ってテストサーバーにデプロイ、動作確認した後、svnのログを見ながら手元のソースをFTPでちまちまアップロード(!)していたけど、modelキャッシュを消し忘れたり更新するファイルが足りなかったり、開発環境用のconfigを上書きして動かなくなったりしてさすがによろしくないと思っていたので改善してみました。
問題
改善案
svn checkout → rsyncでデプロイ
1はcheckoutだと.svnが作られるので避けていたのですが、checkout → rsyncで.svnを除いてミラーするようにしました。
svn checkout --force http://trac/svn/myProject/trunk chmod -R 777 trunk/app/tmp rsync -av --delete --exclude *.svn --exclude app/tmp/sessions/sess* --exclude app/tmp/logs/*.log trunk/* /var/www/html/myProject/
差分だけの処理になって、テストサーバーへのデプロイがだいぶ速くなりました。
2のセッション切れは対策は --exclude app/tmp/sessions/sess* でセッションファイルを除外することで対応しました。ログファイルも除外対象に。
lftpでデプロイ
3のFTPでの更新は、テストサーバーにデプロイしたものをlftpでミラーリングするようにしました。
HOSTNAME="ftp.example.com" FTPUSER="ftpuser" FTPPASS="ftppass" LOCAL_DIR=/var/www/html/myProject REMOTE_DIR=public_html/myProject if [ -d $LOCAL_DIR ] then lftp <<-END open -u $FTPUSER,$FTPPASS $HOSTNAME set ftp:list-options -a lcd $LOCAL_DIR mkdir -p $REMOTE_DIR cd $REMOTE_DIR echo [before mirror] pwd ls # mirror mirror -Rev -X app/tmp/sessions/sess* -X app/tmp/logs/*.log # set permission chmod -R 777 app/tmp/ # delete cache mrm app/tmp/cache/models/cake* mrm app/tmp/smarty/templates_c/*.php echo [after mirror] pwd ls END else echo "LOCAL_DIR=$LOCAL_DIR is not found." fi
これでセッションファイルとログファイルを除外して差分をミラーしてますが、
mkdir -p $REMOTE_DIR cd $REMOTE_DIR
ここが失敗するとftprootにミラーがかかって大事なファイルが消えたりするのでmirrorコマンドをコメントして事前に動作確認されることをお勧めします。できればpwdの結果を見て実行中止する処理を入れたいところ。
本番環境/開発環境のconfig自動切替
4のconfigの切替は、サーバーのIPアドレスで自動判定にしました。
開発環境のIPアドレスを決め打ちで開発用config、それ以外のときに本番用configに切り替えます。
bootstrap.php
<?php if (stripos($_SERVER['SERVER_ADDR'], '127.') === 0 || stripos($_SERVER['SERVER_ADDR'], '192.168.1.') === 0) { define('PRODUCTION', false); } else { define('PRODUCTION', true); } // 本番環境と開発環境で切り替えるものをここに定義 if (PRODUCTION) { // 本番用 } else { // 開発用 } ?>
database.php
<?php class DATABASE_CONFIG { var $production = array( 'driver' => 'postgres', 'connect' => 'pg_connect', 'host' => '127.0.0.1', 'port' => '5432', 'login' => 'db_user', 'password' => 'db_pass', 'database' => 'db_host', 'schema' => 'public', 'prefix' => '', ); var $development = array( 'driver' => 'postgres', 'connect' => 'pg_connect', 'host' => '192.168.1.10', 'port' => '5432', 'login' => 'db_user', 'password' => 'db_pass', 'database' => 'db_host', 'schema' => 'public', 'prefix' => '', ); var $test = array( 'driver' => 'postgres', 'connect' => 'pg_connect', 'host' => '192.168.1.10', 'port' => '5432', 'login' => 'testdb_user', 'password' => 'testdb_pass', 'database' => 'testdb_host', 'schema' => 'public', 'prefix' => '', ); public function __construct() { if (PRODUCTION) { $this->default = $this->production; } else { $this->default = $this->development; } } } ?>
まとめ
svn exportのスクリプトとlftpのスクリプトの2ステップで正しい状態で本番環境にデプロイできるようになりました。
CakePHPのデプロイは手作業だとミスが起きやすいので自動化をおすすめします。
ほぼ一人開発なのでこんな感じですが、規模が大きかったりデプロイ先が複数あったりするならcapistrano, webistrano等のデプロイツールを検討すると良いかと思います。