サービスを運用する場合、開発、運用で複数の環境でサーバーを動かしている場合がよくあると思います。このとき、パラメータ設定の口が柔軟でないと設定値の変更がしにくかったり、サーバーのビルドを環境毎にしなければならなず(特に docker 使っている場合)、デプロイに時間がかかったりします。
そうならないために環境名 (dev,stg,prod) を使用して動作変更するのをやめることをおすすめします。記事内では以下のような環境があると想定し、Javascript (Node.js) でいくつかの例を示します。
- 開発時ローカル PC
- ステージングサーバー環境
- 本番サーバー環境
変数を環境名に依存させるのをやめよう
サーバーでエラーが起きたときに管理者にメールを送るというケースで送り先を分ける場合で説明します。
##悪い例(コード内で環境ごとのメールアドレスを決めている)
コード内で設定されているアドレスにしか送ることができません、送信するメールアドレスが変更になったときはコードの変更が必要。
// process.env.NODE_ENV に環境名が指定されている
function sendErrorMail() {
let email = 'default@example.com';
switch(process.env.NODE_ENV) {
case 'development':
email = 'dev@admin.com';
break;
case 'staging':
email = 'stg@admin.com';
break;
case 'production':
email = 'prod@admin.com';
break;
default:
break;
}
// sendMail は email アドレスとメール本文を指定してメールを送る関数
sendMail(email, 'Server Error Occurred');
}
##良い例(環境変数としてメールアドレス自体を指定している)
メールアドレスが変更になったときでも環境変数の指定を変更するだけで送信先が変更できる
// process.env.ADMIN_EMAIL_ON_ERROR にエラー時のメール送り先が指定されている
function sendErrorMail() {
// sendMail は email アドレスとメール本文を指定してメールを送る関数
sendMail(process.env.ADMIN_EMAIL_ON_ERROR, 'Server Error Occurred');
}
動作を環境名に依存させるのをやめよう
次も似た例ですが、ログのレベル設定を例に説明します。 logWarn
という警告ログを出力する関数があるとします。開発環境だったら debug ログを出す、というパターンはよくあると思いますが、一つの環境変数としてログレベルを設定すると柔軟です。
悪い例(コード内で環境名でレベルを決めている)
// process.env.NODE_ENV に環境名が指定されている
function logWarn(message) {
if (process.env.NODE_ENV == 'development') {
console.warn(message);
}
}
良い例(ログレベルを環境変数として設定する)
const LogLevel = {
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
TRACE: 4,
};
// process.env.LOG_LEVEL にログレベルが設定されている
function logWarn(message) {
if (process.env.LOG_LEVEL <= LogLevel.WARN) {
console.warn(message);
}
}
最後に
この話は主流にありつつある(すでに主流?) Docker でのサーバーデプロイの背景が大きいです。Docker image を build して デプロイしてという流れで運用している場合、ちょっとした動作の変更によって Docker image の build し直ししなければならないとか、環境毎に image を build し直さなければけ無いとなると、build 時間はわりとかかるケース(色々なケースがありますが、数分から10分は最低でもかかると思います)が多いので、build し直ししなくてもいいように(実行時に環境変数として設定すればいいだけにするために)設定類は個別の設定毎に外出ししていくと便利だと考えています。