CakePHP3.5以降の設定情報の切り替えで .env を使うべきか app_local.php を使うべきか

先日開催された CakePHP Meetup イベントにて、.env と app_local.php に対する話題がでました。これらは環境ごとに異なる値を管理するために利用されるものですが、どちらを使えばいいのか明確な基準がなく、なんとなくでイベントは話題が流れていきました。後から気になって色々調べたので、こちらにご紹介します。
先に結論ですが、プロジェクトによってどちらかを選べばよく、特に理由がなければ app_local.php を利用した方がいいという感じでした。明確に片一方が素晴らしいということはありませんでした。

.env の使い方

こちらは環境変数に値をセットする方式で、その値にアクセスするには env() 関数を利用します。例えばDB の設定情報は以下のように記述します。

# .env
export DATABASE_HOST="production.database.host"
export DATABASE_NAME="my_production_db"
export DATABASE_USERNAME="production_user"
export DATABASE_PASSWORD="production_password"
// config/app.php
'Datasources' => [
    'default' => [
        'className' => Connection::class,
        'driver' => Mysql::class,
        'persistent' => false,
        'host' => env('DATABASE_HOST', 'db'),
        'username' => env('DATABASE_USERNAME', 'my_app'),
        'password' => env('DATABASE_PASSWORD', 'secret'),
        'database' => env('DATABASE_NAME', 'my_app'),
        'timezone' => 'Asia/Tokyo',
        'flags' => [],
        'cacheMetadata' => true,
        'log' => false,
        'quoteIdentifiers' => false,
    ],
],

慣れている方は普通のことではないかと感じるかと思いますが、ミートアップイベントで話題にあがったのは cakephp/app 内、config/bootstrap.php 内に以下のコメントがあったからです。

It is HIGHLY discouraged to use a .env file in production, due to security risks and decreased performance on each request. The purpose of the .env file is to emulate the presence of the environment variables like they would be present in production.

https://github.com/cakephp/app/blob/3.8.0/config/bootstrap.php#L52

簡潔に訳すと、セキュリティリスクとパフォーマンス低下の観点から .env を本番環境で利用するのはやめた方がいいとのことです。なんてこった。
.env を有効化させるコードの直前に書いてあるコメントなので気づけましたが、さらっと大切なことをコメントから教えられました。さらには .env.default という .env ファイルを作成するためのサンプルにもネガティブなコメントがありました。

Having this file in production is considered a SECURITY RISK and also decreases the boostrap performance of your application.

https://github.com/cakephp/app/blob/3.8.0/config/.env.default#L7

そして再度公式マニュアルを調べていくと、 app_local.php で環境ごとに異なる値を管理して app.php の内容を上書きする方法が紹介されていました。

https://book.cakephp.org/3/en/development/configuration.html#configuring-your-application

app_local.php の使い方

特段難しいことはなく、先ほどの app.php の上書きしたい内容のみキーを合わせて設定し、bootstrap.php のコメントアウトされているコードを動くようにすれば完了です。

// app_local.php
<?php

return [
    'Datasources' => [
        'default' => [
            'host' => 'production.database.host',
            'username' => 'production_user',
            'password' => 'production_password',
            'database' => 'my_production_db',
        ],
    ],
]
// bootstrap.php
/*
 * Load an environment local configuration file.
 * You can use a file like app_local.php to provide local overrides to your
 * shared configuration.
 */
Configure::load('app_local', 'default');

ミートアップイベントでなんとなく話したことですが、パフォーマンスの低下は都度環境変数へ書き込むため、セキュリティリスクは php のアプリケーションの外側へ値を設定するということが挙げられましたが、明確にコミッター達へ聞いた訳ではないので、あくまでも推測になります。

どちらを使うべきか

プロジェクトによってデプロイや管理ツールは異なるため、どちらか一方が素晴らしいということは言えないとのことでした。kubernetes 使っているプロジェクトもあるし、ansible/puppet/chef などもあるしとのことです。なので、最適な方をオプトインしてくださいといった感じのようです。

Using environment variables will make deployments in kubernetes or other container based hosting simpler, while ‘local’ files make applications living on servers managed by ansible/puppet/chef easier. I’m not confident we can make a decision in either direction here, as each style is used for a different deployment style, and choosing only one will likely make the other harder, and choosing both adds complexity and opportunity for confusion. The current opt-in approach we have lets people choose the style they need.

https://github.com/cakephp/app/issues/707#issuecomment-529236177

終わりに

私はこれらをふまえると、今後は app_local.php で管理しようかと思いました。パフォーマンスの低下とセキュリティに加え、公式マニュアルの上の方に書かれているので app_local.php の方がお勧めだろうと推測しました。何か明確にいい理由があればこちらのお問い合わせより教えていただけると助かります。

Enjoy!!