CakePHP2.1をgit push一発でデプロイ

やはりデプロイは自動化しなければまずいということで。全て手で書き換え+ftpでアップロード状態からgit push一発で完了させるようにしました。ディレクトリの配置や環境は前記事準拠です。
CakePHP2.1をさくらのレンタルサーバー+マルチドメイン使用でデプロイ

やったこと
前提

Gitでソースのバージョン管理をしている

コードで環境の差分を吸収

開発環境と本番環境で設定が異なる部分を、全てコードで吸収します。
僕の場合書き換えたのは以下の4ファイルです。

  • ・bootstrap.php
  • ・core.php
  • ・database.php
  • ・webroot/index.php

基本方針は、IPを見て場合分けです。
bootstrapに定義したURL定数と、coreのdebug設定をこんな感じで書き換え

if (env('SERVER_ADDR') !== '127.0.0.1') {
  #本番処理
} else {
  #開発処理
}


databaseはコンストラクタを定義。設定の配列$devと$prodを作って$defaultに割り当て

  public function __construct() {
    if (env('SERVER_ADDR') !== '127.0.0.1') {
      $this->default = $this->prod;
    }else {
      $this->default = $this->dev;
    }
  }
ちなみに後のマイグレーション時に本番DBへ接続しに行ってエラーに…
indexは env('SERVER_ADDR') が使えず、 $_SERVER["REMOTE_ADDR"] を使ってルート、コアのパスを設定
if ($_SERVER["REMOTE_ADDR"] !== '127.0.0.1') {
  #本番処理
} else {
  #開発処理
}


同一コードで正常に動作することを確かめます。CSSや画像パスの設定が必要な場合もあります。僕はbootstrap内で定数ROOT_URL、ASSETS_URLを切り替えて運用しています。

DBのマイグレーション

CakeDC / migrations
データベースのスキーマ変更が自動で反映されるようにします。スキーマファイル(schema.php)と現在のデータベースを比較し、差分を埋める作成時刻付のマイグレーションファイルを作成。schema_migrationsテーブルでマイグレーションファイルの適用状況を管理し、未適用のものを実行という流れみたいです。

インストール

プラグインフォルダに展開

#myapp(app)/Plugin
$ git clone https:github.com/CakeDC/migrations.git

デプロイ時に一緒に本番サーバーにも入る予定でしたが、他のリポジトリで管理されてるファイルは自動的にignoreされるんですね…僕は.gitフォルダを削除しました。これでpush時に本番にもPluginが設置されます。

開発環境でマイグレーションの準備

まずは開発環境のデータベーススキーマを本番環境で再現。既に本番に作ってあっても大丈夫です。


#schema_migrationsテーブルを作成
$ cake Migrations.migration -p Migrations
#最初のマイグレーションファイルを作成
$ cake Migrations.migration generate
ちなみにここで本番環境を見に行きエラーが発生したので、一時的にdatabase.phpを書き換えて対応しました…

本番環境でのマイグレーションの実行

開発環境で作成したマイグレーションファイルを本番に設置した上で、以下の手順を踏めば本番環境にデータベースを再現できます。


#schema_migrationsテーブルを作成
% cake Migrations.migration -p Migrations
#未適用のマイグレーションファイルを実行
% cake Migrations.migration all

既に本番環境にテーブル等作成済みの場合エラーが発生します。成功したことにしますか?と聞かれるので、成功したことにすれば問題ないです。
An error occurred when processing the migration:
  Migration: 1339467948_first_migration
  Error: Table "areas" already exists in database.
---------------------------------------------------------------
Do you want to mark the migration as successful?. [y]es or [a]bort. (y/a)

スキーマ変更の手順

開発環境で現在のスキーマを準備→テーブルを変更→マイグレーションファイルを作成→スキーママイグレーションファイルを本番にpush→本番で実行の流れです


 #開発で

#
その時点のschema.phpを作成

$ cake schema generate
 #ここでSQLでもツールでもいいのでテーブルの構造を変更する
#
差分のマイグレーションファイルを作成
$ cake Migrations.migration generate

 #本番で
#
未適用のマイグレーションファイルを実行
% cake Migrations.migration all

git push をフックにスクリプト実行

大まかには、変更をcommit→リモートリポジトリにpush→pushをフックにスクリプトが実行され本番環境にpull+追加処理でデプロイ完了という流れです。

さくらレンタルサーバーにgitを導入


#一時ディレクトリを作り移動
% mkdir /home/user/tmp
% cd /home/user/tmp

#wgetアーカイブを拾ってくる
#アーカイブを解凍

% tar xvf git-git-v1.7.11-rc2-0-ga1a031d.tar.gz
% cd git-git-42e15c9
#gmakeでビルド
% gmake
% gmake install

#$HOME/binにインストールされ、$HOME/binがパスに追加されている


#.cshrcを読み込むと、gitコマンドが使える
% source /home/user/.cshrc

リモートリポジトリの追加

まずは本番サーバーにログインしリモートリポジトリを作成


#リポジトリ用のディレクトリ作成
% mkdir /home/user/repos/myapp.git

#bareリポジトリ(作業ディレクトリをもたないリポジトリ)作成
% cd myapp.git
% git init --bare

続いて開発環境のリポジトリに今作成したリモートリポジトリを登録


#既存のリポジトリにリモートリポジトリとして登録
$ git remote add origin user@user.sakura.ne.jp:/home/user/repos/myapp.git
#pushで変更を反映
$ git push origin master

フックスクリプトの作成

gitはリポジトリへの行動をフックにスクリプトを実行する機能を持っています。
.git/hooks内のファイルに記載し、ファイル名から.sampleを取り除けば実行されます。自分で作成する場合はスクリプトに実行権限を与える必要があります。
今回はpushをフックにしたいのでpost-updateを使用

% mv /home/user/repos/myapp.git/hooks/post-update.sample /home/user/repos/myapp.git/hooks/post-update

内容は以下の通り
#!/bin/sh

#リモートリポジトリから本番環境への展開
(cd /home/user/myapp(app); git --git-dir=.git pull)
#webroot内のファイルの転送
(cp -r /home/user/myapp(app)/myapp(webroot)/* /home/user/www/myapp(webroot)/)
#マイグレーションの実行
(cd /home/user/myapp; cake Migrations.migration all)

リモートリポジトリから本番環境への展開

myappディレクトリを置きたい場所に、先ほどのリモートリポジトリからclone

% git clone user@user.sakura.ne.jp:home/user/repos/myapp.git

あとはgit pullでファイルが展開されます。シェルスクリプト内では --git-dir=.git と指定する必要があるみたいです。

webroot内のファイルを転送

今回のサーバー環境では、appとwebrootの位置関係が変わっています。元のリポジトリと構造が違うので、pullした後app/webroot内のファイルを公開フォルダ上にコピーすることにしました。

% cp -r /home/user/myapp(app)/myapp(webroot)/* /home/user/www/myapp(webroot)/)
なお、mvコマンドは同名ファイルに対して処理ができません。gitの場合変更があったファイルのみ転送されるため、いったんディレクトリを削除してmvもできないので、cpを使います。

マイグレーションの実行

未実行のマイグレーションファイルがあれば実行してくれます。

振り返ると結構色々やったなと。今はかなりプロダクトに集中したいのですが、デプロイ自動化の恩恵は相当大きいので、やってよかったと思います。今回はサーバー1台の運用で恩恵が小さいと判断しましたが、時間を見つけてcapistranoも勉強したいところです。