LoginSignup
3
1

More than 1 year has passed since last update.

docker-composeを用いてローカルでfirebase functionsを実行する

Last updated at Posted at 2022-01-23

はじめに

firebase functionsを用いて手軽にAPIを公開したいと思い、ローカル開発環境構築を行いましたので、その構築メモを記載しました。

API開発に向けてローカルでの開発環境を構築するためには、firebase CLIをインストールし、設定をしなければいけません。
しかし、以下3点の理由からdockerコンテナ内で開発できる環境を用意することにしました。
* ローカル環境を汚したくない
* 環境依存しない形で書きたい
* (将来的に)別のfirebaseアカウントに簡単に切り替えられるようにしておきたい

前提条件

  • docker, docker-composeがインストールされていること

ファイルの準備

フォルダ構成

今回は環境変数を.envファイルでまとめて管理できるような構成にしました。

/
┝ firebase/
│ └ Dockerfile 
┝ .env
└ docker-compose.yml

docker-composeファイル

$で始まる変数は、後述の.envファイルから読み取っています

docker-compose.yml
version: '3'
services:
  firebase:
    build:
      context: ./firebase
      args:
        WORKDIR: $WORKDIR
    volumes:
      - ./firebase:/$WORKDIR
    ports:
      - "$FIREBASE_CLI_PORT:$FIREBASE_CLI_PORT"
      - "$FIREBASE_UI_PORT:$FIREBASE_UI_PORT"
      - "$FIREBASE_FUNCTIONS_PORT:$FIREBASE_FUNCTIONS_PORT"
    tty: true

Dockerfile

コンテナ内でfirebase CLI(firebase-tools)をインストールしています。

Dockerfile
FROM node:14-alpine
ARG WORKDIR
ENV HOME=/${WORKDIR} \
    LANG=C.UTF-8 \
    TZ=Asia/Tokyo \
    HOST=0.0.0.0
WORKDIR ${HOME}

RUN yarn global add firebase-tools

CMD ["/bin/sh"]

.envファイル

これは好みですので直接docker-composeファイルに書いてもOKです。
ここでは、ポート番号やフォルダ等の設定を変数として.envファイルで管理し、docker-composeで読み込むようにしています。

.env
WORKDIR=app
FIREBASE_CLI_PORT=9005
FIREBASE_FUNCTIONS_PORT=5001
FIREBASE_UI_PORT=4000

9005: firebase CLIの設定時の通信ポート
5001: firebase functions通信ポート
4000: firebase エミュレータをブラウザから見られるようにする
これらのポートを開けておくことで、ゲストOSとfirebaseへの接続、ホストOSからゲストOSへのAPI接続確認が可能になります。

dockerコンテナ立ち上げ

docker-composeをビルド・立ち上げ

docker-compose build
docker-compose up -d

コンテナ内に入る
※ベースのdockerイメージにalpineを利用したためashコマンドになっている

docker-compose exec firebase ash

以降の手順はdockerコンテナ内で行う

コンテナ内でのfirebase設定

今回はdocker-compose.ymlの設定によりワークスペースのパスを/appにしているため、/app/firebase直下でfirebase CLIコマンドを実行します

cd /app/firebase
firebase login
firebase init functions

これで/app/firebase 下にファイルが作成されます。
サーバを立ち上げる前に、firebase.jsonを以下のように変更することで、ホストOSからアクセスできるようにしておきます。

※ハマりポイント
ホストOSからlocalhostでアクセスする場合は、
ゲストOS内のfirebase APIが0.0.0.0でlistenするようにしなければならない

firebase.json
{
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  },
  "emulators": {
    "functions": {
      "host": "0.0.0.0",
      "port": 5001
    },
    "ui": {
      "enabled": true,
      "host": "0.0.0.0",
      "port": 4000
    }
  }
}

サーバ実行

このままでも実行することはできますが、一つのfunctionsに対し1つしかAPIを定義できません。そのため、expressライブラリを利用し複数APIを作成できるようにしました。今回は例として、indexファイルを以下のように書き換え、/helloへアクセスするとHello Express!と表示するAPIを作成しました。

src/index.ts
import * as functions from "firebase-functions";
const express = require("express");

const app = express();

app.get('/hello', (req:any, res:any) => {
  // レスポンスの設定
  res.send('Hello Express!');
});

const api = functions.https.onRequest(app);
module.exports = { api };

以下コマンドを実行して立ち上がるか確認します。

npm run serve

立ち上がると以下のような文字がコンソールに出力されます。

i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "/app/functions" for Cloud Functions...
✔  functions[us-central1-api]: http function initialized (http://0.0.0.0:5001/xxx).

ここで http://0.0.0.0:5001/xxx がapiのベースurlになります。

最後にホストOSのブラウザからhttp://0.0.0.0:5001/xxx/hello へアクセスして、ブラウザ上で"Hello Express!"と表示されれば完了です。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1