Firebase Local Emulator Suiteとは|ローカル再現の構成とCI組み込み【2026年8月時点】
Firebase Local Emulator Suite は、Cloud Firestore・Authentication・Cloud Functions といった Firebase のプロダクトを開発機の上で動かすツール群です。firebase-tools に同梱され、firebase emulators:start で立ち上がります。この記事で扱うのは、再現できるプロダクトの範囲と既定ポート、firebase.json の設定、テストデータの入出力、セキュリティルールの自動検証、CIへの組み込みまで。最後に本番と挙動が食い違う4箇所を挙げ、どこから実プロジェクトで確かめるかの線を引きます。数値と版番号は2026年8月時点の実測値です。
まとめ:実装検証はローカルへ、インデックスと権限は本番で確かめる
エミュレータを入れる価値は、課金と本番データを触らずにトリガー関数やセキュリティルールを何度でも壊せる点にあります。開発機に JDK 11以降が要ること、プロダクトごとに別ポートで起動すること、この2つを押さえれば導入は数分で終わります。CIへ載せるなら firebase emulators:exec です。公式が「継続的インテグレーションのワークフローには一般にこちらが適する」と述べているとおり、テストスクリプトの終了に合わせてエミュレータを畳んでくれます。
最も事故になるのは、通ったテストを本番の保証と取り違えることです。Firestore エミュレータは複合インデックスを追跡せず、有効なクエリをすべて実行します。Functions エミュレータはIAMの挙動を再現しません。インデックス・権限・上限・実行時間の4つは、実プロジェクトで確かめる工程として別に持ってください。
Emulator Suiteが再現するプロダクトと既定ポートの割り当て
エミュレータはプロダクトごとに独立したプロセスとして立ち上がり、それぞれ別のポートを持ちます。まず再現範囲を確定させます。
Firestore・Auth・FunctionsとHostingを含む対応範囲
公式のポート表に並ぶのは、Authentication、Cloud Firestore、Realtime Database、Cloud Storage for Firebase、Cloud Functions、Firebase Hosting、App Hosting、Pub/Sub、Eventarc の9つで、これに管理画面である Emulator Suite UI が加わります。概要ページの記述では Cloud Functions・Pub/Sub・Firebase Extensions の3つがベータ扱いでした。
この一覧に載らないプロダクトは対象外で、Analytics や Crashlytics のような計測・レポート系はエミュレータを持ちません。起動そのものは Firebase CLI のコマンド群の一部で、firebase-toolsの認証とデプロイ運用をまとめた記事ではエミュレータを4系統のうちの1つとして位置づけています。
既定ポート9種の割り当てと衝突時にfirebase.jsonで変える箇所
既定値は次のとおりです。8080番や5000番は他のローカルサーバーと衝突しやすく、そのときは firebase.json の emulators セクションで該当プロダクトの port を書き換えます。
| エミュレータ | 既定ポート |
|---|---|
| Emulator Suite UI | 4000 |
| Firebase Hosting | 5000 |
| Cloud Functions | 5001 |
| App Hosting | 5002 |
| Cloud Firestore | 8080 |
| Pub/Sub | 8085 |
| Realtime Database | 9000 |
| Authentication | 9099 |
| Cloud Storage | 9199 |
| Eventarc | 9299 |
ポートを変えたら、アプリ側の接続先も同じ番号へ揃えます。片方だけ直して接続できないという詰まり方が最も多いところ。9000番で動くRealtime Database本体の同期の仕組みと転送量課金は別記事で扱いました。
JDK 11以降とNode版の食い違いを踏まえた実行環境の前提
公式が挙げる前提は Node.js 16.0以降、JDK 11以降、Firebase CLI 8.14.0以降の3点です。Java が要るのは Firestore・Realtime Database・Cloud Storage・Pub/Sub のエミュレータが Java 実装のためで、JDK が無い端末では起動時点で落ちます。
Nodeの記述には注意してください。npm registry で実測した firebase-tools 15.27.0 の engines 指定は >=20.0.0 || >=22.0.0 || >=24.0.0 で、ドキュメントの「16.0以降」より要求が上がっています。Node 18系ではエミュレータ以前に firebase-tools のインストールが通りません。CIイメージは Node 20系以上を選び、版を固定してください。
firebase.jsonのemulators設定とSDKを向け直す接続の作り方
設定は firebase.json の emulators セクションに集約されます。ここに書かれていないエミュレータは起動しません。
firebase init emulatorsが生成する設定と手で足す項目
firebase init emulators を実行すると、対話形式で選んだプロダクトのぶんだけ emulators セクションが生成されます。並ぶのは各プロダクトの port、UIの enabled と port、そして singleProjectMode です。UIを止めたければ enabled を false にします。
初期化時に選ばなかったエミュレータは、後から firebase init emulators を回し直すか、セクションへ直接書き足せば追加できます。プロジェクト作成からCLI導入までの前段はFirebaseの導入手順を工程別に整理した記事で扱っているので、そこまで終わった状態から入ってください。
singleProjectModeの警告とプロジェクトID取り違えの防ぎ方
Local Emulator Suite は、環境の中に複数のプロジェクトIDを検出すると警告を出します。singleProjectMode を false にすればこの挙動を上書きできますが、消す前に理由を確認してください。多いのは .firebaserc のエイリアスとアプリ側の設定オブジェクトが別プロジェクトを指しているケースで、放置するとエミュレータへ向いていない側の呼び出しが本番へ飛びます。CIでは -P フラグで対象を明示し、警告が出た時点で構成を疑うほうが安全です。
connectFirestoreEmulatorと環境変数で向け先を切り替える書き分け
アプリをエミュレータへ向ける経路は2つあります。クライアントSDKからはプロダクト別の接続関数を呼び、サーバー側とテストランナーからは環境変数で指定します。
Web のモジュラーSDK(実測で firebase 12.17.1 が最新)では connectFirestoreEmulator(db, '127.0.0.1', 8080) の形で、データベースのインスタンス・ホスト文字列・ポート番号を渡します。名前空間版のAPIでは db.useEmulator("127.0.0.1", 8080) が対応する呼び出しでした。
サーバー側は環境変数です。Firestore なら FIRESTORE_EMULATOR_HOST、Authentication なら FIREBASE_AUTH_EMULATOR_HOST を設定します。後者を設定すると、Firebase Admin SDKの初期化とユーザー管理の解説で扱っている Admin SDK が、エミュレータの発行した署名なしIDトークンとセッションクッキーを受け付けます。本番デプロイ先に同じ環境変数が残らないよう、CIとデプロイで環境変数は分けてください。
テストデータのimportとexportで作る検証の再現性と持ち回り
エミュレータは終了時にデータを破棄します。同じ初期状態から検証を始めたいなら、入出力のフラグを前提に組みます。
–importと–export-on-exitで検証の初期状態を固定する運用
--import にディレクトリを渡すと、保存済みのデータを読み込んでエミュレータのメモリ内データを上書きします。--export-on-exit はシャットダウン時の自動書き出しで、両方を同時に指定した場合、書き出し先は明示しない限り読み込み元と同じディレクトリになりました。裏返しとして、デバッグで壊したデータもそのまま保存されます。検証用のシードを固定したいときは --export-on-exit を外し、読み込み専用で回してください。
firebase-export-metadata.jsonの出力先とGitへ載せる粒度
手動で書き出すコマンドは firebase emulators:export で、出力ディレクトリに firebase-export-metadata.json というマニフェストが生成されます。どのエミュレータのデータがどのファイルに入っているかはこのマニフェストが持つため、ディレクトリごと扱うのが前提です。
リポジトリに載せてよいのは、権限判定の分岐を踏むのに要る最小のユーザーとドキュメントだけ。本番からダンプした実データを持ち込むと、個人情報が開発機とCIランナーの両方に複製されます。シードは生成スクリプトから作り、そのスクリプトをバージョン管理する形が扱いやすいところです。
セキュリティルール検証をrules-unit-testingへ寄せる構成
エミュレータを入れる動機として大きいのがセキュリティルールの検証です。npm registry の実測では、専用ライブラリ @firebase/rules-unit-testing の最新が 5.0.1 でした。
initializeTestEnvironmentで作る認証済みと未認証のコンテキスト
入口は initializeTestEnvironment() で、これが返す RulesTestEnvironment からテスト用のクライアントを取り出します。特定ユーザーとして振る舞うのが authenticatedContext()、未ログイン状態が unauthenticatedContext() です。
前準備でデータを仕込むときは withSecurityRulesDisabled() を使います。ルールを無効にした状態でセットアップ関数を走らせる仕組みで、これが無いと「ルールに阻まれてテストデータを置けない」という循環に陥ります。テスト間の後始末は clearFirestore()、Realtime Database なら clearDatabase()、Cloud Storage なら clearStorage()。最後に cleanup() で全コンテキストを破棄します。実行にはエミュレータの起動と FIRESTORE_EMULATOR_HOST などの環境変数が要ります。
assertSucceedsとassertFailsで許可と拒否を対で押さえる書き方
assertSucceeds() はルール違反なく解決することを、assertFails() はルール違反で拒否されることを表明します。この2つは必ず対で書いてください。
許可側だけを並べたテストでは「誰でも読める状態」を検出できません。1つのコレクションにつき、所有者による読み書き(成功)、他人による読み取り(失敗)、未認証での書き込み(失敗)の3本を最低ラインに置くと、ルールを緩めた変更がCIで止まります。Firebase Authenticationの認証方式と導入手順の解説で対応プロバイダを確認したうえで、テスト側のコンテキストを揃えます。
ruleCoverageレポートで未評価のルール条件を洗い出す手順
書いたテストがルールのどの行を踏んだかは、エミュレータが持つカバレッジレポートで確認できます。Cloud Firestore は localhost の8080番に対して emulator/v1/projects/[データベース名]:ruleCoverage.html というパスでHTMLレポートを返し、末尾を :ruleCoverage にするとJSONになります。Realtime Database は9000番の .inspect/coverage?ns=[データベース名] です。
レポート上では各ルール式の評価が展開され、マウスオーバーで詳細を追えます。踏まれていない条件が残っていれば、そこはテストが無いか、到達不能な条件かのどちらか。後者ならルール自体を削る判断になります。なお Cloud Storage 向けのカバレッジレポートは公式に記載がありません。
emulators:execでCIへ組み込む起動制御と実行時間の削り方
ローカルで動くところまで来たら、次はCIです。選ぶコマンドと起動対象が、パイプラインの実行時間をそのまま決めます。
emulators:startとemulators:execの違いとCIで選ぶ側の判断
両者の差は寿命の管理です。firebase emulators:start は起動したまま前面に残り、開発者が手で止めるまで動き続けます。対して firebase emulators:exec は、エミュレータの起動・指定したスクリプトの実行・シャットダウンを1回の呼び出しでまとめて行いました。公式も「継続的インテグレーションのワークフローには一般に emulators:exec のほうが適する」と明記しています。
CIで emulators:start をバックグラウンド起動して待ち時間を挟む構成は、ジョブがハングしたときにランナーを占有し続けます。素直に exec へ寄せてください。
–onlyで起動対象を絞りCIの待ち時間を削るときの取捨選択
起動するエミュレータは --only で絞れます。Firestore のルールだけを検証するジョブなら firebase emulators:start --only firestore、Realtime Database なら --only database、Cloud Storage なら --only storage のように指定します。
削る効果が大きいのは Java 実装のエミュレータです。Firestore・Realtime Database・Cloud Storage・Pub/Sub はJVMの起動を伴うため、要らないものを外すと立ち上がりが短くなります。逆に、Functions のトリガーを検証するジョブでは発火元のエミュレータを外せません。ジョブをルール検証と関数検証に分け、それぞれ必要最小の --only を渡す構成が扱いやすいところ。Hosting の配信確認はFirebase Hostingの配信とリリース管理を整理した記事と合わせて読んでください。
本番シークレットへの参照を.secret.localで断ち切る設定
見落としやすいのが Functions エミュレータのシークレットです。公式の記述では、エミュレータは Application Default Credentials を通じて本番のシークレットへアクセスしようとします。ローカルで動かしているつもりでも、実際には本番の Secret Manager を読んでいる状態になり得るということ。
制限された環境やCIでは .secret.local ファイルに値を書いて上書きできます。本番資格情報がCIランナーへ流れる経路も同時に塞げます。このファイルはリポジトリに含めず、CIのシークレットストアから配置してください。AIコーディング支援からFirebase MCPサーバーでFirestoreを操作させる構成でも、接続先をエミュレータへ向けておけばクラウド側のデータには届きません。
エミュレータと本番の挙動が食い違う4箇所と受託開発での採用条件
公式ドキュメントが自ら挙げている非再現の範囲を、事故の起き方とセットで並べます。
複合インデックス未追跡でCIが通り本番で失敗する典型パターン
Firestore エミュレータは複合インデックスを追跡せず、有効なクエリであればすべて実行します。公式もこの点を明記したうえで、本番で必要になるインデックスの洗い出しは実際の Cloud Firestore に対して行うよう求めています。
結果として起きるのが、複数フィールドの等価条件と範囲条件を組み合わせたクエリがローカルでは即座に返り、本番デプロイ後に FAILED_PRECONDITION で落ちるという流れです。ステージング用の実プロジェクトを1つ持ち、主要クエリを一度そこで流してエラーメッセージからインデックス定義を回収し、firestore.indexes.json に固定してください。
トランザクションのロック解放が最大30秒かかる場合のタイムアウト
トランザクションについて、公式は「本番で見られるすべての挙動を実装していない」と述べています。1つのドキュメントへ並行して書き込む機能を検証する場合、エミュレータは書き込み要求の完了が遅くなり、ロックの解放に最大で30秒かかることがあります。
テストランナーの既定タイムアウトは5秒前後のものが多く、そのままでは在庫の同時更新やカウンタの排他制御を扱うテストが不定期に落ちます。原因をアプリのバグと読み違えると調査が長引くところ。該当するテストだけタイムアウトを引き上げ、コメントで理由を残してください。
IAMと本番の上限を再現しないエミュレータが取りこぼす検証範囲
Local Emulator Suite は、IAM に関する挙動を再現も尊重もしません。公式の表現では、ローカルスクリプトを直接実行したときと同様に、開発マシン上でグローバルに利用可能なアカウントで動きます。サービスアカウントの権限不足はローカルでは顕在化しません。
上限も同様です。本番なら大きすぎるとして拒否されるトランザクションが、エミュレータでは通る場合があります。Functions 側ではメモリやプロセッサの制限が課されず、実行時間も本番と異なり、コンテナ化された本番環境そのものを模してもいません。コールドスタートによる遅延はローカルでは見えないということ。
受託開発でエミュレータへ寄せる条件と実プロジェクトを残す場面
線引きを言い切ります。エミュレータへ寄せてよいのは、セキュリティルールの許可と拒否、Firestore・Realtime Database・Authentication・Pub/Sub をトリガーとする関数の分岐、データ移行スクリプトの流し込み、サインイン経路の分岐まで。Auth エミュレータはSMSの確認コードを端末へ送らずターミナルへ出力するため、電話番号認証の分岐もローカルで踏めます。
一方、次の3つの場合は採用しません。本番相当の負荷やコールドスタートを測りたい案件、IAMの権限設計そのものがリスクの中心にある案件、reCAPTCHA や APNs を伴う電話認証の実挙動を確認する案件です。Auth エミュレータが発行するIDトークンは署名なしで、他の Firebase エミュレータか設定済みの Admin SDK しか受け付けません。外部サービスへトークンを渡す連携の検証には使えないということ。
内製化を前提とした引き継ぎでは、firebase.json の emulators セクション、シードデータの生成スクリプト、ルールのテストコード、CIの exec 定義の4点を1セットで渡すと、その後の改修を発注元だけで回せます。この整備と引き継ぎ後の運用設計は、Webシステムの保守運用と内製化支援でご相談を受けています。
よくある質問
Firebase Local Emulator Suite の導入検討で問い合わせの多い5点をまとめます。
Firebase Local Emulator Suiteの利用に料金はかかりますか?
エミュレータ自体は開発機の上で動くため、Firebase 側の課金は発生せず、読み書きの回数も本番のクォータを消費しません。例外は2つ。Cloud Functions エミュレータは既定で本番の Secret Manager を参照しに行き、エミュレータへ向けていないSDK呼び出しが混ざれば実プロジェクトへ届きます。Blaze プランの要否や超過単価はFirebaseの料金をまとめた記事で扱っています。
エミュレータを止めるとデータは消えますか?
消えます。エミュレータはシャットダウン時にデータベースの内容をクリアします。残したい場合は firebase emulators:export で書き出すか、起動時に --export-on-exit を付けてください。次回は --import で同じディレクトリを読み込めば復元されます。クライアント側のオフラインキャッシュは自動でクリアされない点にも注意が要ります。
Javaを入れずにエミュレータを動かせますか?
公式が挙げる前提条件に JDK 11以降が含まれており、Cloud Firestore・Realtime Database・Cloud Storage・Pub/Sub のエミュレータは Java 実装です。JDK が無い環境ではこれらの起動が失敗します。CIのコンテナイメージを軽くしたい場合でも、対象エミュレータを使うジョブには JDK を含めてください。
エミュレータのテストが通れば本番でも動きますか?
そうとは限りません。公式ドキュメント自身が非再現の範囲を挙げており、複合インデックスの追跡、トランザクションの完全な挙動、本番の各種上限、IAMの権限判定、Functions の失敗時リトライ、メモリとCPUの制限はいずれも対象外でした。再試行を前提にしたべき等な実装はCloud Functions for Firebaseとは|トリガー設計と第2世代の実装判断で整理しています。担保できるのはロジックとルールの正しさまで。ステージング用の実プロジェクトを1つ用意し、リリース前に主要な導線を通してください。
Cloud Functionsのバックグラウンドトリガーはローカルで発火しますか?
発火します。Cloud Functions エミュレータは、Realtime Database・Cloud Firestore・Authentication・Pub/Sub・Firebase alerts の各エミュレータからのバックグラウンドトリガーに対応しており、呼び出し可能関数(callable)とタスクキュー関数も扱えます。ただし失敗時のリトライには非対応です。指数バックオフを前提にした再実行の設計は、この構成では確かめられません。
関連記事
- Firebase CLIとは:起動元である firebase-tools の認証方式とデプロイのフラグを扱っています。
- Firebaseの導入手順:プロジェクト作成からSDK導入と初回デプロイまで、エミュレータを組む前段です。
- Firebase Hostingとは:
--only hostingで確認する配信の仕組みとプレビューチャネルの運用です。 - Firebase Authenticationとは:Auth エミュレータで再現する認証方式の、本番側の設定と料金です。
- Firebase Admin SDKとは:
FIREBASE_AUTH_EMULATOR_HOSTでエミュレータのトークンを受け付ける側の初期化です。