😇

Firebase Local Emulator Suiteの環境をDockerで用意する

2023/05/15に公開

概要

  • いまさらながらタイトル的なことをやる
  • いまさらといいながらなぜ?と思うかと思いますが、Meilisearch周りの記事書きたいのでこの話を先にやっておきたい
    • じゃないと記事が長くなる

Firebase Local Emulator Suiteとは

https://firebase.google.com/docs/emulator-suite?hl=ja

Firebase Local Emulator Suite は、アプリのビルドとテストをローカルで行うことのできる、デベロッパー向けの高度なツールセットです。使用できる機能には、Cloud Firestore、Realtime Database、Cloud Storage for Firebase、Authentication、Firebase Hosting、Cloud Functions(ベータ版)、Pub/Sub(ベータ版)、Firebase Extensions(ベータ版)があります。充実したユーザー インターフェースを備えており、アプリの本稼働やプロトタイピングにかかる時間を短縮できます。

という感じのものです(ドキュメントからのコピペ)

Firebase、いい感じで安いんですが、ローカルでガチャガチャ叩くだけとか、CI回したいとかあると思うんですが、そのたびにGCP環境を叩いてしまうと、無料枠消費しちゃうし、場合によっては課金されてしまい辛いので、Emulatorを使っていきましょう。

注意点として、すべての機能がEmulatorでは達成することができないので、利用する機能が含まれているかドキュメントを確認しながら進めていくことをおすすめします。

環境構築

前提

  • GCPでFirebaseプロジェクトを作成済み
  • フロントが動くコンテナを用意して、そこから環境変数次第でEmulatorを叩けるようにする
  • 進めているプロジェクトは下記サービスを利用しています
    • Firestore
    • Firebase Autentication
    • Cloud Functions
    • Firebase extensions
    • Firebase Hosting

ディレクトリ構成

./docker/firebase
├── Dockerfile
├── bin
└── config

./functions/
./extensions/

.firebaserc
firebase.json
firestore.indexes.json
firestore.rules

ディレクトリの用意

$ mkdir -p docker/firebase/{bin,config}
$ mkdir functions
$ mkdir extensions

Dockerfileを用意する

./docker/firebase/Dockerfile

FROM ubuntu:22.04

RUN apt update && \
apt install -y curl openjdk-17-jdk && \
curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
apt install -y nodejs

RUN npm install -g firebase-tools

compose.ymlを用意する

./compose.yaml

front という名前のコンテナは動作確認用です。

services:
  front:
    image: node:lts-slim
    working_dir: /app
    tty: true

  firebase:
    build:
      context: .
      dockerfile: ./docker/firebase/Dockerfile
    volumes:
      - ./.firebaserc:/opt/firebase/.firebaserc
      - ./firebase.json:/opt/firebase/firebase.json
      - ./firestore.indexes.json:/opt/firebase/firestore.indexes.json
      - ./firestore.rules:/opt/firebase/firestore.rules
      - ./docker/firebase/bin/:/root/.cache:cached
      - ./docker/firebase/config/:/root/.config:cached
      - ./functions:/opt/firebase/functions
      - ./extensions:/opt/firebase/extensions
    ports:
      - 9099:9099 # Firebase Authentication
      - 5001:5001 # Clound Functions
      - 8080:8080 # Cloud Firestore
      - 9000:9000 # Realtime Database
      - 5000:5000 # Firebase Hosting
      - 8085:8085 # Cloud Pub/Sub
      - 9199:9199 # Cloud Storage
      - 4000:4000 # Emulator Suite UI
    working_dir: /opt/firebase
    command: firebase emulators:start

必要なファイルを用意する

.firebaserc

自分のプロジェクト名に差し替える。

{
  "projects": {
    "default": "${PROJECT_ID}"
  }
}

firebase.json

compose.yaml の方と合わせる。(可能であれば環境変数とかで同じ値になるようにしたい)

{
  "emulators": {
    "auth": {
      "host": "0.0.0.0",
      "port": 9099
    },
    "functions": {
      "host": "0.0.0.0",
      "port": 5001
    },
    "firestore": {
      "host": "0.0.0.0",
      "port": 8080
    },
    "hosting": {
      "host": "0.0.0.0",
      "port": 5000
    },
    "ui": {
      "host": "0.0.0.0",
      "enabled": true
    },
    "singleProjectMode": true
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "extensions": {
  }
}

firestore.indexes.json

こんな感じのファイル。Firestoreで作成したインデックスの設定ファイル。

{
  "indexes": [
    {
      "collectionGroup": "${COLLECTION_NAME}",
      "queryScope": "COLLECTION",
      "fields": [
        {
          "fieldPath": "${FIELD_NAME1}",
          "order": "ASCENDING"
        },
        {
          "fieldPath": "${FIELD_NAME2}",
          "order": "ASCENDING"
        }
      ]
    }
  ]
}

自分でせっせと確認してファイルを作るのは大変なので、すでにGCPにFirestoreの環境があるのであれば、エクスポートしたほうが楽です。

firebase firestore:indexes >firestore.indexes.json

もしまだ作成していないのであれば、空ファイルでもおk

firestore.rules

既存のものがあるなら、Firebaseコンソール(GCP)からコピペしておいてください。

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write
    }
  }
}

GCPへログイン

cliからログインを行い、tokenを発行します。

下記コマンドを実行すると、ブラウザからGoogleアカウントで認証してくれURLが発行されるので、それをブラウザにコピペして認証作業を進めてください。

$ docker compose run --rm firebase firebase login --no-localhost

表示されたtokenをコピペしてcliに渡したらおkです。

また、そのあとにこんなディレクトリが作成されたおk.

$ ls -ld docker/firebase/config/configstore/

動作確認

$ docker compose up -d

ログで確認してみます。

$ docker comopse logs -f

# ...
ubuntu-firebase-1  | ┌─────────────────────────────────────────────────────────────┐
ubuntu-firebase-1  | │ ✔  All emulators ready! It is now safe to connect your app. │
ubuntu-firebase-1  | │ i  View Emulator UI at http://127.0.0.1:4000/               │
ubuntu-firebase-1  | └─────────────────────────────────────────────────────────────┘
ubuntu-firebase-1  |
ubuntu-firebase-1  | ┌────────────────┬──────────────────────────────────┬──────────────────────────────────┐
ubuntu-firebase-1  | │ Emulator       │ Host:Port                        │ View in Emulator UI              │
ubuntu-firebase-1  | ├────────────────┼──────────────────────────────────┼──────────────────────────────────┤
ubuntu-firebase-1  | │ Authentication │ 0.0.0.0:9099                     │ http://127.0.0.1:4000/auth       │
ubuntu-firebase-1  | ├────────────────┼──────────────────────────────────┼──────────────────────────────────┤
ubuntu-firebase-1  | │ Functions      │ 0.0.0.0:5001                     │ http://127.0.0.1:4000/functions  │
ubuntu-firebase-1  | ├────────────────┼──────────────────────────────────┼──────────────────────────────────┤
ubuntu-firebase-1  | │ Firestore      │ 0.0.0.0:8080                     │ http://127.0.0.1:4000/firestore  │
ubuntu-firebase-1  | ├────────────────┼──────────────────────────────────┼──────────────────────────────────┤
ubuntu-firebase-1  | │ Hosting        │ Failed to initialize (see above) │                                  │
ubuntu-firebase-1  | ├────────────────┼──────────────────────────────────┼──────────────────────────────────┤
ubuntu-firebase-1  | │ Extensions     │ 0.0.0.0:5001                     │ http://127.0.0.1:4000/extensions │
ubuntu-firebase-1  | └────────────────┴──────────────────────────────────┴──────────────────────────────────┘
ubuntu-firebase-1  |   Emulator Hub running at 127.0.0.1:4400
ubuntu-firebase-1  |   Other reserved ports: 4500, 9150
ubuntu-firebase-1  | ┌─────────────────────────┬───────────────┬─────────────────────┐
ubuntu-firebase-1  | │ Extension Instance Name │ Extension Ref │ View in Emulator UI │
ubuntu-firebase-1  | └─────────────────────────┴───────────────┴─────────────────────┘
ubuntu-firebase-1  | Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
ubuntu-firebase-1  |

Emulatorはローカルで管理画面を確認することができます。

http://localhost:4000/

Tips

Firestoreのデータを一括で削除

コンテナを落とすとデータが削除されますが、テストを実行するたびに既存データを削除したいユースケースがあると思います。

本番に機能はない(らしい。試していない。怖いから)ですが、Emulator向けにクリアするAPIがあるので、毎度それを叩けばおkです。

https://firebase.google.com/docs/emulator-suite/connect_firestore?hl=ja

検証で用意したFirestoreのデータを保存したい

コンテナを落とすとデータが削除されるので、テストデータを用意しておきたい場合に利用します。
※わざわざジェネレート用のスクリプト作って突っ込んでた。。。

$ firebase emulators:export ./data/export_my_data -P default
$ firebase emulators:start -P default --import=./data/export_my_data

https://zenn.dev/meijin/articles/marp-firebase-emulator#データの-export%2Fimport

GitHub Actionsで動かしたい

TBD

参考記事

CBcloud Tech Blog

Discussion