CakePHPのデプロイ

svn, rsync, lftpを使ったデプロイ

開発環境はWindows、テストサーバーはCentOS、本番サーバーはFreeBSD
CakePHP1.2、開発環境とテストサーバーはDB共用で、本番サーバーのDBはlocalhostという環境。
バージョン管理はSubversion(Trac)を利用。
本番サーバーはFTPでしかアクセスできない。

今まではテストサーバーにsvn exportしてapp/tmp を777にするスクリプトを作ってテストサーバーにデプロイ、動作確認した後、svnのログを見ながら手元のソースをFTPでちまちまアップロード(!)していたけど、modelキャッシュを消し忘れたり更新するファイルが足りなかったり、開発環境用のconfigを上書きして動かなくなったりしてさすがによろしくないと思っていたので改善してみました。

問題

  1. svn exportするのに時間がかかる(vendorsがでかい)
  2. svn export後にセッションが切れる(ログインし直し面倒)
  3. FTPのファイル更新忘れ(ごめんなさい)
  4. 開発環境の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等のデプロイツールを検討すると良いかと思います。