毎度のこと、このリポジトリを使用して作業を進めていきます。
前提
- DockerでFirebaseEmulatorを動かしたい人
- Firebase Emulatorのセットアップが完了していること(firebase.jsonを確認)
- Firebase Storageのセットアップが完了していること
- Firebase Authのセットアップが完了していること
ディレクトリ構成
詳細はこちらをご覧ください
containers/
├── Dockerfile
├── bin
├── config
├── data
├── export.sh
└── start_firebase.sh
docker-compose.yml
package.json
yarn.lock
node_modules
.output
.firebaserc
firebase.json
firestore.indexes.json
firestore.rules
storage.rulesDockerfile
エミュレーターを動かすだけなので、基本的にこのままでいいと思います。
FROM ubuntu:20.04
RUN apt update && \
    apt install -y ca-certificates-java && \
    update-ca-certificates -f && \
    apt install -y curl openjdk-17-jdk && \
    curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
    apt install -y nodejs imagemagick
RUN npm install -g yarn firebase-tools
RUN ln -sf /usr/share/zoneinfo/Japan /etc/localtimedocker-compose.yml
コンテナ名やvolumesは各々お好きなように。
ちなみにFirebase Functionsには対応させておりませんのでご了承を。
version: '3.9'
services:
  firebase:
    container_name: study-firebase
    build:
      context: .
      dockerfile: ./containers/Dockerfile
    volumes:
      - ./package.json:/usr/src/app/package.json
      - ./yarn.lock:/usr/src/app/yarn.lock
      - ./node_modules/:/usr/src/app/node_modules
      - ./.output/:/usr/src/app/.output
      - ./.firebaserc:/usr/src/app/.firebaserc
      - ./firebase.json:/usr/src/app/firebase.json
      - ./firestore.indexes.json:/usr/src/app/firestore.indexes.json
      - ./firestore.rules:/usr/src/app/firestore.rules
      - ./storage.rules:/usr/src/app/storage.rules
      - ./containers/:/usr/src/app/containers
      - ./containers/bin/:/root/.cache:cached
      - ./containers/config/:/root/.config:cached
    ports:
      - 9099:9099 # Firebase Authentication
      - 8080:8080 # Cloud Firestore
      - 5000:5000 # Firebase Hosting
      - 9199:9199 # Cloud Storage
      - 4000:4000 # Emulator Suite UI
      - 9150:9150 # Firestore Emulator UI websocket
    working_dir: /usr/src/app
    command: ./containers/start_firebase.sh ${EXPORT_INTERVAL}
    tty: trueもし認証情報が必要な場合は以下のコマンドを。
docker compose run --rm firebase firebase login --no-localhost
ちょっとした問題点
通常、エミュレータ起動のコマンドの引数に--export-on-exitをつければ、終了時にエクスポートできるのですが…
どうにも再起動時にデータが保存されていないようで、各所で悲鳴が上がっています。
定期的にexportする
docker-compose.ymlにも記載しましたが、./containers/start_firebase.sh ${EXPORT_INTERVAL} としています。
ちょっと力技な気がしますが、デフォルトで60秒おきに。EXPORT_INTERVAL=0とすると保持しないようにしています。
#! /bin/bash
SCRIPT_DIR="$(dirname "$0")"
BASE_DIR="$(dirname "$SCRIPT_DIR")"
DATA_DIR="${BASE_DIR}/containers/data"
# Set export interval
EXPORT_INTERVAL=${1:-60}
if ! [[ $EXPORT_INTERVAL =~ ^[0-9]+$ ]]; then
  echo "デフォルトの60秒に設定します。"
  EXPORT_INTERVAL=60
fi
echo "INTERVAL: ${EXPORT_INTERVAL}"
# Javaオプションを設定し、Firebaseエミュレータを起動
export JAVA_TOOL_OPTIONS="-Xms4g -Xmx8g"
TZ=JST firebase emulators:start --project=default --import="${DATA_DIR}" &
# エミュレータが起動したかどうかをチェック
EMULATOR_URL="http://127.0.0.1:4000"
MAX_RETRIES=5
for ((i=1; i<=MAX_RETRIES; i++)); do
  sleep 5
  if curl -LI "${EMULATOR_URL}" -o /dev/null -w '%{http_code}\n' -s | grep -q "200"; then
    echo "Firebaseエミュレータが起動しました。"
    break
  fi
  echo "エミュレータの起動を待っています... 試行回数 $i / $MAX_RETRIES"
done
# スクリプト終了時の処理関数
cleanup() {
  echo "Firebaseエミュレータを停止しています..."
  firebase emulators:export "${DATA_DIR}"
  exit
}
# シグナルトラップの設定
trap cleanup SIGINT SIGTERM
# 定期的なエクスポート
while [ ${EXPORT_INTERVAL} -ne 0 ]; do
  sleep "${EXPORT_INTERVAL}"
  "${SCRIPT_DIR}/export.sh"
done
waitエクスポート用のスクリプトは以下の通り。
#! /bin/bash
SCRIPT_DIR="$(dirname "$0")"
BASE_DIR="$(dirname "$SCRIPT_DIR")"
DATA_DIR="${BASE_DIR}/containers/data"
firebase emulators:export -f ${DATA_DIR}おわり
今後この環境で認証、テストなどを書いていきます。
今回の記事では要点のみを書いておりますので、試したい方はこちらのリポジトリをご参考にどうぞ。
