Firebase Local Emulator Suiteの環境をDockerで用意する
概要
- いまさらながらタイトル的なことをやる
- いまさらといいながらなぜ?と思うかと思いますが、Meilisearch周りの記事書きたいのでこの話を先にやっておきたい
- じゃないと記事が長くなる
Firebase Local Emulator Suiteとは
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はローカルで管理画面を確認することができます。
Tips
Firestoreのデータを一括で削除
コンテナを落とすとデータが削除されますが、テストを実行するたびに既存データを削除したいユースケースがあると思います。
本番に機能はない(らしい。試していない。怖いから)ですが、Emulator向けにクリアするAPIがあるので、毎度それを叩けばおkです。
検証で用意したFirestoreのデータを保存したい
コンテナを落とすとデータが削除されるので、テストデータを用意しておきたい場合に利用します。
※わざわざジェネレート用のスクリプト作って突っ込んでた。。。
$ firebase emulators:export ./data/export_my_data -P default
$ firebase emulators:start -P default --import=./data/export_my_data
GitHub Actionsで動かしたい
TBD
Discussion