docker-compose × Firebase Emulatorでローカル環境構築

5 min read

※本記事はこちらのスライドを marp で変換して作成する元になった markdown ファイルです

Firebase の使いどころ

課題

  • 当時:ステージング用 Firebase を各開発者がローカルでも利用
    • データやアカウント情報が混ざってややこしい
  • Web バックエンド(MySQL + Laravel/NestJS)との連携
    • MySQL で発行した uid をベースとしたカスタムトークン認証をやっているので、uid が各々の環境でかぶって混乱する

Emulator の概要

  • CLI から擬似的な Firebase 環境を起動できる仕組み
    • localhost はもちろん、コンテナ内や CI でも起動できる
    • Auth/Firestore/Functions/Hosting 等に対応

主な利用用途

  • Firestore のセキュリティルールのテスト
  • docker-compose で共通の network を使うことで、MySQL が発行した uid を共通で利用するなどの連携ができる

Emulator セットアップの全体的な流れ

  • Docker コンテナ作成
    • Node.js コンテナの Dockerfile を書く
    • docker-compose.yml で他コンテナのネットワークと接続
  • コンテナを起動する
    • bash で入り込み、エミュレータを起動する
  • ソースコードの書き換え
    • 環境変数を見て、Emulator の利用可否を分岐する

Docker コンテナ作成

FROM node:10-buster

RUN apt-get update -y

RUN apt-get install -y curl openjdk-11-jre-headless

RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
    && apt-get install -y nodejs

RUN npm install -g firebase-tools && mkdir functions

COPY ./package.json ./
COPY ./yarn.lock ./
COPY ./functions/package.json ./functions/.
COPY ./functions/yarn.lock ./functions/.

docker-compose.yml

version: '3.7'

networks:
  server:
    external:
      name: XXXXXX

services:
  firebase:
    build:
      context: .
      dockerfile: ./docker/local/Dockerfile
    volumes:
      - ./:/opt/workspace:cached
    ports:
      - 9099:9099 # Auth
      - 4000:4000 # Emulator Suite UI
      - 5001:5001 # Cloud Functions
      - 8080:8080 # Cloud Firestore
    environment:
      USE_LOCAL_BACKEND: 1
    working_dir: /opt/workspace
    networks:
      - server
    command: bash -c 'yarn && cd functions && yarn && /bin/bash'
    tty: true

docker-compose.yml ポイント

Web コンテナの docker-compose network と接続する
これにより http://nginx 等で Web に接続できるし、Web からも http://firebase:9099 等の URI で Emulator に接続できる

networks:
  server:
    external:
      name: XXXXXX_default

Emulator の起動画面(Firestore)

http://localhost:4000/firestore

h:450

データの Export/Import

以下のコマンドで Emulator 内のデータは出し入れできるので、
基本的なデータを入れたら Seeder 代わりに開発メンバー間で共有するのがおすすめ

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

フロントエンドから呼び出し

useAuth/useFirestore/useStorage(Storage は将来に期待)という命名で export

const enabledEmulator = () => process.env.USE_FIREBASE_EMULATOR

export const useAuth = () => {
  auth = firebase.app().auth()
  if (enabledEmulator()) {
    auth.useEmulator('http://localhost:9099')
  }
  return auth
}

フロントエンドから呼び出し2

ざっくりこんな感じです

useAuth().onAuthStateChanged((user) => {
  state.firebaseUser = user;
});
const collection: CollectionReference<Room> = useFirestore().collection(
  "rooms"
);

バックエンド(例:NestJS)からの呼び出し

AdminSDK からの接続も Emulator 対応している

docker-compose で接続しているのでホスト名は firebase

import * as admin from "firebase-admin";
// ...
admin.firestore().settings({
  host: "firebase:8080",
  ssl: false,
});

React Native Emulator と接続

Nuxt⇔React Native 間でのリアルタイムチャットがローカル環境完結で実現できる!

bg right:50% w:100%

Storage には未対応

  • Auth/Firestore/Functions/Hosting に並んでよく使われていると思われる Storage には未対応
  • つまり、Storage の動作確認をしたければそこだけステージングの Firebase に引き続きアップロードされる
    • セキュリティルールとか、Function のテストとかは相変わらず生の Firebase を使わないといけない
    • 各開発者が個人用の Firebase を持って運用するのも一案

所感

  • 思ったより完成度が高かった
    • 特に Firestore を hook にした Functions が動くのはちょっと感動
    • Admin SDK も Emulator を向いて使える
    • Auth は Custom Token を使った認証もいける
  • 今後の課題
    • Storage 対応

告知

私が CTO を務めている「オンライン家庭教師マナリンク」では、エンジニアを募集しております。

2020/11/28 現在、Web エンジニア及び、React Native エンジニアを探しております。

マナリンクでは、オンライン家庭教師という生き方を選択している先生方が稼げるように、サイト上で自身のプロフィールを魅力的に発信できるようにしたり、オンライン指導専用アプリをリリースするなど、次々にプロダクトを開発しています。エンジニアでいうフリーランスのような生き方を、教育関係者の方々にも提供することを目指す事業です。

日々新しい技術を勉強して、試す機会を探している方にはうってつけかな環境と思います。僕も、半年間 Next.js を個人で勉強し続けた結果、新規メディア立ち上げの機会を得て早速 Next.js でリリースができました。

興味あれば Twitter に DM 等でご連絡をください!


もし記事が参考になれば、Zenn でサポートいただければ嬉しいです。
技術書・カンファレンス等に当てさせていただきます!

この記事に贈られたバッジ