Playframewok 2.0 での環境ごとの設定の切替方法について考えてた

備忘録ですお。

継続的デリバリー曰く「あらゆる環境に同じバイナリをデプロイせよ」

開発環境とか本番環境だとかで同じ設定を使っているなんてことは、まぁ、殆ど無いと思います。
DBの接続先とか、外部サービスのURIだったりとか。
なので、開発にデプロイする時と本番にデプロイする時で設定情報を切り替える必要があるわけですが、よく取られるアプローチとしては任意の環境用にビルドするというのがあると思います。*1
つまり

build devel

とか

build prod

みたいなことをして、それぞれの環境用の設定で、それぞれの環境用のバイナリを作るというアプローチです。
しかし、継続的デリバリーはこう言っています。
「いろんな環境に簡単にデプロイできるようになるし問題の切り分けしやすくなるから、どの環境にデプロイするかにかかわらず同じバイナリ使え。」
そうなると、アプリケーション本体には設定へのポインタだけを記述しておいて、設定は別で管理する必要があります。

Playframeworkの場合

Playは設定情報をconfディレクトリ配下のapplication.confから読み込みます。
Play 1.x の時代にはデプロイ先のサーバにインストールされているPlayに対して任意の「フレームワークID」を振ることが出来、application.conf内の設定キー名にフレームワークIDを含めることで、自身がデプロイされている環境*2に応じて選択する設定が切り替わる仕組みでした。
が、Play 2.0 からはフレームワークIDが廃止されています。*3
そうなると前述よろしく任意環境専用のバイナリをビルドするしか無い…わけではなく、Playはサーバ起動時に利用するconfファイルを以下のようにコマンドライン引数で指定することができます。*4

# クラスパスから探す
target/start -Dconfig.resource=devel.conf &

# クラスパス外のファイルシステムから探す(絶対パス)
target/start -Dconfig.file=/path/to/devel.conf &

なので、「prod.conf」や「devel.conf」みたいな環境ごとの設定ファイルを作っておいて、サーバ起動時に指定するのがよさそうです。
あらかじめconfファイル名を環境変数に設定しておけば、起動スクリプトの環境依存もなくなって良い感じ。

export CONF=devel.conf
target/start -Dconfig.resource=$CONF &

ちなみに

Playの設定ファイルは

include "application.conf"

と書くことによって指定したファイルの情報を継承*5することができるので、application.confの内容をデフォルトとしてincludeし、環境ごとに差異がある部分を上書きする、みたいなことをすれば設定の管理も楽になりそうです。

*1:mavenのプロファイルとか

*2:にセットアップされているPlayframework

*3:PlayアプリケーションがPlayへ依存しないようにするため?

*4:2.0.2の時点では、デバッグモード時は何故かconfig.resourceが効かず、config.fileを利用しないとダメでした

*5:正確にはHOCONオブジェクトの上書き、マージ