[Firebase] Functionsで環境変数を参照/設定する

Firebaseでの「環境変数」は、OSなどから提供される情報が得られる物と、Firebaseが独自に提供する2種類の機能があります。前者が他の環境でも一般的に環境変数と呼ばれる物ですね。

ここではそれぞれの利用方法を見ていきます。

Firebaseの独自機能

独自の環境変数を新たに設定したくなったら、原則こちらを利用します。Firebaseがこの領域にデータを保存することはないので何か重要な情報を上書きしてしまうことがなく安全です。システム全体で利用できるグローバル変数のように扱うことができます。

CLIで設定する

値はCLIからセットします。当初firebase.jsonなどに記録されるかと思ったのですが、挙動を見るに直接Firebaseのサーバへ記録に行ってるようですね。

以下はslack.apiという名前に、THE API KEYという値をセットしています。ドット(.)の前がカテゴリのような物だと思ってください。

$ firebase functions:config:set slack.apikey="THE API KEY"
✔  Functions config updated.

現在の設定をCLIから確認する場合は以下のコマンドを実行すると、JSON形式で表示されます。

$ firebase functions:config:get
{
  "slack": {
    "apikey": "THE API KEY"
  }
}

削除するにはキーを指定して次のコマンドを実行します。ドットの前にあるカテゴリを指定すると内部にあるすべての環境変数を一括で削除できます。

$ firebase functions:config:unset slack
✔  Environment updated.

$ firebase functions:config:get
{}

Functionsで利用する

functions.config()に続いて設定した環境変数のキーを指定すればアクセスできます。

const functions = require('firebase-functions');

exports.printenvSlack = functions.https.onRequest( (req, res) => {
  res.send( functions.config().slack.apikey );
});

上記コードだとキーが存在しなかった場合に実行時エラーとなりますので、実際にはもう少し丁寧に書いた方が安全ですw

const functions = require('firebase-functions');

exports.printenvSlack = functions.https.onRequest( (req, res) => {
  const config = functions.config();
  if( config.slack && config.slack.apikey ){
    res.send( config.slack.apikey );
  }
  else{
    res.send("Not Found Config");
  }
});

ローカルのテストで利用したい

ローカルで開発する際にfirebase serveしてサーバを起動するわけですが、このままだ環境変数が利用できません。サーバ起動前に以下のコマンドを実行しておく必要があります。

$ firebase functions:config:get > functions/.runtimeconfig.json

functionsフォルダの下に置かないと認識してくれないようです。この作業を行ったあとにローカル用のサーバを起動します。

$ firebase serve

最初知らなかったときはかなりハマりましたw

一般的な意味での環境変数

こちらはOSやFirebaseなどから提供される情報が詰まっています。新たな変数を設定することも可能ですが特別な理由がない場合はやめて置いた方が良いでしょう。

環境変数を参照する

Node.jsの場合、環境変数はprocess.envに連想配列(ハッシュ)として入っているので、シンプルに以下のようなコードで参照できます。

const functions = require('firebase-functions');

exports.printenv = functions.https.onRequest( (req, res) => {
  res.send(`このFunctionのリージョンは${process.env.FUNCTION_REGION}です`);
});

環境変数を追加する

追加も連想配列(ハッシュ)を操作するのと変わりません。

const functions = require('firebase-functions');

// 現在時間をセットする
process.env["NOW"] = new Date().getTime();

exports.printenvNow = functions.https.onRequest( (req, res) => {
  res.send(process.env.NOW);
});

書いておいて何ですが、こちらは何か事情がない限りは利用しない方が良いでしょう。独自の環境変数を設定する場合は前述のFirebaseの独自機能を使うのが安全です。

環境変数を一覧表示

単にconsole.log(process.env)した結果をWebの管理画面から確認できます。以下のようなコードを用意しfirebase deploy、その後URLを叩いて実行します。

const functions = require('firebase-functions');

exports.printenv = functions.https.onRequest( (req, res) => {
  console.log(process.env);
  res.send("Please check firebase dashboard.");
});

実行したらFirebaseの管理画面へログインし、左メニューの「Functions」、右側の「ログ」をクリックするとデバッグ用の情報が表示されます。この中から先ほどの結果を探します。

実際の内容

以下は実際の内容を文字コードでソートした物です。眺めているとFirebaseはほんとにGCPの上で動いているのを再確認させられますねw

項目 初期値
CODE_LOCATION /srv
DEBIAN_FRONTEND noninteractive
ENTRY_POINT printenv
FIREBASE_CONFIG {"projectId":"(プロジェクト名)","databaseURL":"https://(プロジェクト名).firebaseio.com","storageBucket":"(プロジェクト名).appspot.com","locationId":"asia-northeast1"}
FUNCTION_IDENTITY projectname@appspot.gserviceaccount.com
FUNCTION_MEMORY_MB 256
FUNCTION_NAME printenv
FUNCTION_REGION us-central1
FUNCTION_TIMEOUT_SEC 60
FUNCTION_TRIGGER_TYPE HTTP_TRIGGER
GCLOUD_PROJECT (プロジェクト名)
GCP_PROJECT (プロジェクト名)
HOME /tmp
NODE_ENV production
NO_UPDATE_NOTIFIER true
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PORT 8080
PWD /srv
SUPERVISOR_HOSTNAME 169.254.8.129
SUPERVISOR_INTERNAL_PORT 8081
WORKER_PORT 8091
X_GOOGLE_CODE_LOCATION /srv
X_GOOGLE_CONTAINER_LOGGING_ENABLED false
X_GOOGLE_ENTRY_POINT printenv
X_GOOGLE_FUNCTION_IDENTITY projectname@appspot.gserviceaccount.com
X_GOOGLE_FUNCTION_MEMORY_MB 256
X_GOOGLE_FUNCTION_NAME printenv
X_GOOGLE_FUNCTION_REGION us-central1
X_GOOGLE_FUNCTION_TIMEOUT_SEC 60
X_GOOGLE_FUNCTION_TRIGGER_TYPE HTTP_TRIGGER
X_GOOGLE_FUNCTION_VERSION 2
X_GOOGLE_GCLOUD_PROJECT (プロジェクト名)
X_GOOGLE_GCP_PROJECT (プロジェクト名)
X_GOOGLE_LOAD_ON_START false
X_GOOGLE_NEW_FUNCTION_SIGNATURE true
X_GOOGLE_SUPERVISOR_HOSTNAME 169.254.8.129
X_GOOGLE_SUPERVISOR_INTERNAL_PORT 8081
X_GOOGLE_WORKER_PORT 8091

おまけ

ダッシュボードに入るのがめんどい場合は適当にWebブラウザへ表示することももちろん可能です。

const functions = require('firebase-functions');

exports.printenv = functions.https.onRequest( (req, res) => {
  let html='<style>dt{font-weight:bold;} dd{margin-bottom:10px;}</style>';

  html += '<dl>';
  for( key in process.env ){
    const value = process.env[key];
    html += `<dt>${key}</dt><dd>${value}</dd>`;
  };
  html += '</dl>';

  res.send(html);
});

参考ページ