Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@kyhei_0727

DockerでFirebase Local Emulator Suiteを起動する。

はじめに

Firebase Local Emulator Suiteはローカル環境でFirestoreやCloud FunctionsといったFirebaseプロジェクトのコンポーネントをエミュレートできる環境です。
https://firebase.google.com/docs/emulator-suite?hl=ja

本記事ではDocker及びDocker Composeを利用して上記の環境を構築したいと思います。

開発環境

  • macOS Catalina 10.15.6
  • Docker Desktop stable 2.3.0.4

なお、本記事で使用したコードはこちらです。

実際に作ってみる。

はじめにFirebaseのプロジェクトを作成しておきましょう。
https://console.firebase.google.com/
後述するEmulator Suite UI(GUI上でエミュレータを管理できるコンソール)を利用するために必要となります。
使用するプロジェクトのIDは.envファイルに控えておきます。

$ mkdir empty_dir && cd empty_dir
$ touch .env
.env
GCP_PROJECT_ID=YOUR_PROJECT_ID

それでは早速Dockerfileから作成していきます。
エミュレータの動作要件を満たすようイメージを作成します。
https://firebase.google.com/docs/emulator-suite/install_and_configure?hl=ja

$ mkdir docker
$ touch ./docker/firebase.dockerfile
docker/firebase.dockerfile
FROM ubuntu:20.04

RUN apt-get update -y

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

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

RUN npm install -g firebase-tools

つづいてDocker Composeの構成ファイルを作成します。
ボリュームのマウントも行うため適宜ディレクトリも作成しておきます。

$ mkdir firebase
$ touch docker-compose.yaml
docker-compose.yaml
version: "3"

networks:
    backend:

services:
    workspace:
        image: golang:1.15
        environment:
            FIRESTORE_EMULATOR_HOST: "firebase:8080"
            GCP_PROJECT_ID: "${GCP_PROJECT_ID}"
        volumes:
            - ./gopath/:/go:cached
            - ./workspace/:/opt/workspace:cached
        ports:
            - 8000:8000
        working_dir: /opt/workspace
        networks:
            - backend
        command: bash
        tty: true
    firebase:
        build:
            context: ./docker
            dockerfile: firebase.dockerfile
        volumes:
            - ./firebase/emulators/:/opt/workspace:cached
            - ./firebase/bin/:/root/.cache:cached
            - ./firebase/config/:/root/.config:cached
        ports:
            - 4000:4000 # Emulator Suite UI
            - 5000:5000 # Firebase Hosting
            - 5001:5001 # Clound Functions
            - 9000:9000 # Realtime Database
            - 8080:8080 # Cloud Firestore
            - 8085:8085 # Cloud Pub/Sub
        working_dir: /opt/workspace
        networks:
            - backend
        command: bash
        tty: true

今回はGo言語からFirestoreのAPIを叩いてみたいと思います。

./workspace/go.mod
module github.com/kyhei/firebase_emu_sample

go 1.15

require (
    cloud.google.com/go/firestore v1.3.0
    golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
    golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
    golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f // indirect
    golang.org/x/tools v0.0.0-20200904185747-39188db58858 // indirect
    google.golang.org/api v0.31.0 // indirect
    google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d // indirect
)
./workspace/main.go
package main

import (
    "context"
    "log"
    "os"

    "cloud.google.com/go/firestore"
)

func main() {
    ctx := context.Background()
    client, err := firestore.NewClient(ctx, os.Getenv("GCP_PROJECT_ID"))
    defer client.Close()
    if err != nil {
        log.Fatal(err.Error())
    }

    doc, _, err := client.Collection("users").Add(ctx, map[string]interface{}{
        "name": "kyhei",
        "age":  123,
    })
    if err != nil {
        log.Fatal(err.Error())
    }

    log.Println(doc.ID)

    q := client.Collection("users").Select("name", "age")
    docs, err := q.Documents(ctx).GetAll()
    if err != nil {
        log.Fatal(err.Error())
    }

    for _, doc := range docs {
        log.Println(doc.Data())
    }

}

ここまでの内容でDocker Composeを実行してみましょう。

$ docker-compose up -d
$ docker-compose ps

2つのコンテナが起動していればOKです。

エミュレータの起動と設定

firebaseコンテナにログインし、Firebaseプロジェクトの初期化を行います。

$ docker-compose exec firebase bash
root@da35c7925947:/opt/workspace# firebase login --no-localhost
root@da35c7925947:/opt/workspace# firebase init

firebase initでは、プロジェクトを既存のものを選択し、
利用サービスの選択肢では、Emulatorsを選びます。(他はなんでもOKです。)

Emulators Setupでは全てのエミュレータにチェックを入れましょう!
その後それぞれに関する設定が聞かれますが全てデフォルトで大丈夫です。

初期化が完了したら、firebase.jsonを編集します。

./firebase/emulators/firebase.json
{
  "emulators": {
    "functions": {
      "host": "0.0.0.0",
      "port": 5001
    },
    "firestore": {
      "host": "0.0.0.0",
      "port": 8080
    },
    "database": {
      "host": "0.0.0.0",
      "port": 9000
    },
    "hosting": {
      "host": "0.0.0.0",
      "port": 5000
    },
    "pubsub": {
      "host": "0.0.0.0",
      "port": 8085
    },
    "ui": {
      "enabled": true,
      "host": "0.0.0.0",
      "port": 4000
    }
  }
}

それでは次のコマンドで実際にエミュレータを起動しましょう。

root@da35c7925947:/opt/workspace# firebase emulators:start

初回は実行ファイルがダウンロードされます。
エミュレータが立ち上がったらhttp://localhost:4000でコンソールにアクセスできればOKです!

スクリーンショット 2020-09-09 16.11.06.png

Firestoreエミュレータの確認

前項で作成したスクリプトを実行して、Firestoreへの接続を確認してみましょう。

$ docker-compose exec workspace bash
root@c64fed9c2890:/opt/workspace# go run main.go
2020/09/09 07:17:08 6WQVScx2NGm4oli8f7iw
2020/09/09 07:17:08 map[age:123 name:kyhei]

コンソールを確認すると無事ドキュメントが追加されているのが確認できます。

スクリーンショット 2020-09-09 18.58.37.png

お疲れ様でした!

Cloud FunctionsやHostingを起動するためにはそれぞれの初期化が必要となります。
エミュレータ起動時のログから初期化のコマンド等が指示されますので、そちらを実行していけばOKです。

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
kyhei_0727
LOVE DRIVEN DEVELOPER web周りを広く浅く楽しんでます
topgate
Google技術を中心に取り扱う技術者集団

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?