Help us understand the problem. What is going on with this article?

Firebase firestoreのバックアップをCloudFunctionsで自動実行してみた

はじめに

atma(あーとま)Advent Calendar 2019 25日目担当のこーたです。
今回はFirestoreを触った知見を共有したいと思います。

前提

Firestoreには自動バックアップ機能がありません。 <-これが結構痛い
そこでFirestore exportのAPIをCloud FunctionsのCloud Pub/Subで定期的に叩いてみました。

結論

簡単に実装出来ました。

index.js
const functions = require("firebase-functions");
// 初期化
const admin = require("firebase-admin");
admin.initializeApp();
// 東京リージョンでデプロイ
const FIREBASE_REGION = "asia-northeast1";
const rp = require("request-promise");
const { google } = require('googleapis');
/**
 * Firebase Cloud Firestoreのバックアップ処理
 */
exports.backupFirestoreData = functions
  .region(FIREBASE_REGION)       
  .pubsub.schedule('0 3 * * *')  //ここで実行隔離を指定
  .timeZone("Asia/Tokyo")       
  .onRun((context) => {
    const projectId = 'projectId'
    const scopes = ['https://www.googleapis.com/auth/datastore', 'https://www.googleapis.com/auth/cloud-platform']
    const key = require(`./${projectId}.json`)  //jsonからGCSへのアクセス権を読み込み
    const url = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`
    const jwtClient = new google.auth.JWT(
      key.client_email,
      key.private_key,
      scopes,
    )
    jwtClient.authorize().then((credentials) => {
      //日付を取得
      require('date-utils');
      const date = new Date();
      date.setTime(date.getTime() + 1000 * 60 * 60 * 9); // JSTに変換
      const formatted = date.toFormat("YYYY_MM_DD_HH24_MI_SS");
      rp.post(url, {
        headers: { Authorization: `Bearer ${credentials.access_token}` },
        json: true,
        body: { outputUriPrefix: `gs://projectId.appspot.com/backup/${formatted}` }
      })
    });
    return null;
  })

必要パッケージ

Date 型を扱いやすくするdate-utilsを使っているのでインストールして下さい。

$ npm install date-utils

or

$ yarn add date-utils

解説

Firestore exportのAPIをCloud FunctionsのCloud Pub/Subで定期的に叩いています。

スクリーンショット 2019-12-24 16.54.25.png

サービスアカウントとは

サービス アカウントは、個々のエンドユーザーではなく、アプリケーションや仮想マシン(VM)に属している特別な Google アカウントです。アプリケーションはサービス アカウントを使用して、ユーザーの関与を必要とせずに Google のサービス API を呼び出すことができます。

  const key = require(`./${projectId}.json`)  //jsonからGCSへのアクセス権を読み込み

この部分でサービスアカウントキーを読み込んでいます。

バックアップ先

Firebase Cloud Storageのアドレスを指定しています。

  body: { outputUriPrefix: `gs://projectId.appspot.com/backup/${formatted}` }

バックアップしたものはこのような感じで保存されます。
スクリーンショット 2019-12-24 16.55.14.png

※projectIdは本来envに記載するべき内容ですが、分かりやすいようにコードに記載しています。

最後に

上記コードではサービスアカウントキーのjsonを渡しています。

その他にApplication Default Credentialsという仕組みがあるみたいです。
https://cloud.google.com/docs/authentication/production?hl=ja
この仕組みを使えばサービスアカウントキーのjsonを渡さずに実装することが可能かもしれません。
次に触る機会がありましたら、この方法での実装も試してみたいです。

以上
Firebase firestoreのバックアップをCloudFunctionsで自動実行してみたでした!

atma_inc
Change the common sense with algorithm を達成するためのスタートアップ
https://atma.co.jp
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした