Home > CakePHP | Heroku > CakePHP2 アプリケーションを Heroku で動かす設定

CakePHP2 アプリケーションを Heroku で動かす設定

この記事の所要時間: 163

CakePHP2 アプリケーションを Heroku 上で動かす設定についてです。

cakephp_logo_250_trans

以前のエントリにも書きましたが、Heroku で Web アプリケーションを動かす際に重要なのは、Web サーバ自体(Heroku では、Dyno)に、アプリケーションの状態(データ、セッション情報、ログ等)を保持させないということです。

Heroku の Dyno は、デプロイの際や、定常的な再起動により、破棄されるため、記録されたファイルは消えてしまいます。よって、こうしたデータファイルは、アドオンなど外部に記録する必要があります。

Heroku では、アドオンを活用するのがポイントですので、ここでは、主に CakePHP アプリケーションからこうしたアドオンと連携する方法を見ていきます。

Environments Library as a plugin

まず、開発環境と Heroku 環境で設定値を切り替えるために Environments Library as a plugin を使います。

https://github.com/josegonzalez/cakephp-environments

これは、CAKE_ENV という環境変数の値で、環境に応じて、データベースやキャッシュなどの設定を切り替えるものです。昨今のフレームワークではお馴染みの機能ですね。

ここでは、下記の設定について切り替えを行います。

  • ログ
  • データベース
  • キャッシュ / セッション

このプラグインでは、まず Config/bootstrap/environments.php を作成します。このファイルで、環境毎の設定ファイルの読み込みを行います。下記では、Heroku 環境用の heroku.php と、開発環境用の development.php を読み込んでいます。

  • Config/bootstrap/environments.php
<?php
CakePlugin::load('Environments');
App::uses('Environment', 'Environments.Lib');

include dirname(__FILE__) . DS . 'environments' . DS . 'heroku.php';
include dirname(__FILE__) . DS . 'environments' . DS . 'development.php';

Environment::start();

次に、Heroku 環境用の Config/bootstrap/environments/heroku.php です。

環境の設定は、Environment::configure() で行います。第一引数に環境名(CAKE_ENVで指定するもの)、第二引数は適用条件(true なら、CAKE_ENV に合致しなければデフォルトとして適用)、第三引数に設定値の連想配列(Configure::write() する)、第四引数にコールバックを指定します。

第三引数で設定する方法もあるのですが、より柔軟な設定を行うために、ここでは、第四引数のコールバックを指定します。実際の設定は、以降で順に指定していきます。

  • Config/bootstrap/environments/heroku.php
<?php
Environment::configure('heroku', false, [
], function () {
    // Heroku 用設定
});

開発環境用の Config/bootstrap/environments/development です。コールバックで、デフォルトの設定を記述しています。

  • Config/bootstrap/environments/development.php
<?php
Environment::configure('development', true, [
], function () {
    // Log settings
    App::uses('CakeLog', 'Log');
    CakeLog::config('debug', array(
        'engine' => 'File',
        'types' => array('notice', 'info', 'debug'),
        'file' => 'debug',
    ));
    CakeLog::config('error', array(
        'engine' => 'File',
        'types' => array('warning', 'error', 'critical', 'alert', 'emergency'),
        'file' => 'error',
    ));

    // Database settings
    Configure::write('DATABASE_OPTIONS', [
        'datasource' => 'Database/Postgres',
        'persistent' => false,
        'host' => 'localhost',
        'login' => 'shin',
        'password' => '',
        'database' => 'app',
    ]);

    Configure::write('TEST_DATABASE_OPTIONS', [
        'datasource' => 'Database/Postgres',
        'persistent' => false,
        'host' => 'localhost',
        'login' => 'shin',
        'password' => '',
        'database' => 'app_test',
    ]);

    // Cache settings
    Cache::config('default', array('engine' => 'File'));
});

次に、database.php での接続情報を、環境ごとに設定できるように下記のようにします。各環境ファイルで Configure::write()
した値を、DATABASE_CONFIG クラスに設定します。

  • Config/database.php
class DATABASE_CONFIG {
    public $default = [];
    public $test = [];

    public function __construct() {
        $this->default = Configure::read('DATABASE_OPTIONS');
        $this->test = Configure::read('TEST_DATABASE_OPTIONS');
    }
}

このプラグインを有効にするために、bootstrap.phpを以下のように変更します。コメント部分は削除しています。

  • Config/bootstrap.php
<?php
require_once __DIR__ . '/../vendor/autoload.php';

include __DIR__ . '/bootstrap/environments.php';

Configure::write('Dispatcher.filters', array(
    'AssetDispatcher',
    'CacheDispatcher'
));

Heroku で環境変数 CAKE_ENV をセット

このアプリケーションが、Heroku にデプロイした際に、heroku.php を利用するように、環境変数CAKE_ENVherokuをセットします。これで、デプロイしたアプリケーションは、heroku 設定で動作するようになります。

$ heroku config:set CAKE_ENV=heroku

ログ

Heroku 環境でのログの設定です。ログは、ファイルではなく、標準出力もしくは標準エラー出力に出力します。

こうしておくと、heroku logs コマンドでログが確認できます。また、Papertail や FlyData のようにログを各サービスへ転送するアドオンを使うと、出力されたログを閲覧したり、S3 などに転送することができます。

ログは、まずは標準出力もしくは標準エラー出力にして、あとそれをどう活用するかは、アドオンに任せるという考え方です。

下記では、アプリケーションログを標準出力へ、エラー出力を標準エラー出力へ出力しています。

  • Config/bootstrap/environments/heroku.php
<?php
Environment::configure('heroku', false, [
], function () {
    // Log settings
    App::uses('CakeLog', 'Log');
    App::uses('ConsoleOutput', 'Console');
    CakeLog::config('debug', [
        'engine' => 'ConsoleLog',
        'stream' => new ConsoleOutput(),
    ]);
    CakeLog::config('error', [
        'engine' => 'ConsoleLog',
        'stream' => new ConsoleOutput('php://stderr'),
    ]);
});

あとは、アドオンと追加すれば、出力されたログがアドオンで利用できます。例えば、Papertrailを以下のコマンドで追加して、アプリケーションを動作させると、Papertrail の画面でログが確認できます。

$ heroku addons:add papertrail

データベース

Heroku のデータベースといえば、PostgreSQL なので、Heroku Postgres を使います。(もちろん、MySQL が良ければ、ClearDB なり、RDS なり使えます。)

$ heroku addons:add heroku-postgresql

Heroku 内では接続情報が環境変数で渡されるので、これをパースします。パースされた情報を、heroku.php で、Configure::write() で、セットしていきます。

  • Config/bootstrap/environments/heroku.php
<?php
Environment::configure('heroku', false, [
], function () {
    // Log settings
    (snip)

    // Database settings
    if (empty(getenv('DATABASE_URL'))) {
        throw new CakeException('no DATABASE_URL environment variable');
    }
    $url = parse_url(getenv('DATABASE_URL'));
    Configure::write('DATABASE_OPTIONS', [
        'datasource' => 'Database/Postgres',
        'persistent' => false,
        'host' => $url['host'],
        'login' => $url['user'],
        'password' => $url['pass'],
        'database' => substr($url['path'], 1),
    ]);
});

キャッシュ / セッション

キャッシュ / セッションのデータストアには、Redis を使います。

ここでは、Redis サービスのアドオンとして、Redis To Go を利用します。

$ heroku addons:add redistogo

データベースと同じく、接続情報が環境変数で渡されるので、それをパース(ホスト、ポート、パスワード)して、セットするだけです。セッションハンドラには、Cache を使いたいので、その指定も行います。

これで、キャッシュもセッションも、Redis To Go に保存されます。

  • Config/bootstrap/environments/heroku.php
<?php
Environment::configure('heroku', false, [
], function () {
    // Log settings
    (snip)

    // Database settings
    (snip)

    // Cache settings
    if (empty(getenv('REDISTOGO_URL'))) {
        throw new CakeException('no REDISTOGO_URL environment variable');
    }
    $url = parse_url(getenv('REDISTOGO_URL'));
    Cache::config('default', [
        'engine' => 'Redis',
        'server' => $url['host'],
        'port' => $url['port'],
        'compress' => false,
        'password' => $url['pass'],
        'serialize' => 'php'
    ]);

    // Session Settings
    Configure::write('Session', [
        'defaults' => 'cache',
    ]);
});

さいごに

ベーシックな部分だけですが、Heroku で CakePHP アプリケーションを動かす設定を見てきました。

ここで紹介した以外では、メールやデータファイル(画像等)など、他にもアプリケーションでは必要なものがありますが、ほとんどのものは、ここで見てきたようにアドオンを活用することで実現できます。

こうした構成にしておけば、Dyno が再起動したり、インスタンス数を増減しても、アプリケーションデータはアドオンに保持されているので、動作に支障はありません。こうしたスケーラブルナ構成にしておくのが、Heroku のような PaaS を活用する肝ですね。

このエントリは、CakePHP Advent Calendar 2014 の 3 日目でした。まだ少し空き枠があるので、CakePHP な何かを書いてみてはどうでしょうか。

Pocket

follow us in feedly

Home > CakePHP | Heroku > CakePHP2 アプリケーションを Heroku で動かす設定

検索
フィード
メタ情報

Return to page top