Firestoreを定期バックアップする

Firestoreを定期バックアップする

November 27, 2021

Google 公式の手引きに従って実施ください、の一言で終わってしまいそうですが、備忘録もかねて記載します。

前提整理 #

バックアップ処理の流れ

(処理の全体像を把握してからの方が作業しやすいと思いますので先に記載)

Cloud Functions で定期実行する処理の中で Firestore からデータをエクスポートし Cloud Storage に格納する。

本記事で説明しないこと

公式ドキュメントには Firebase CLI をインストールするところから記載がありますが、ここではローカルに Firebase プロジェクトが作成されている状態を前提として進めます。

言語

TypeScript で記載します。

1. Cloud Storage にバケットを作成する #

既存のバケットにバックアップデータを格納するならば新規バケットの作成不要ですが、大抵は専用のバケットを作ると思います。

Firebase コンソールの Storage からバケットを追加します。各項目の内容は任意です。

  • 新しいバケットを作成
    • バケットリファレンス | gs://example-project-db-buckup-backet
    • ロケーション | ASIA-SOUTHEAST1
    • アクセス頻度 | アーカイブ

2. 必要なパッケージをインストールする #

公式ドキュメントでは手順が明記されていませんが、以下2つのパッケージをインストールする必要があります。

npm i @google-cloud/firestore
npm i firebase-functions

3. Cloud Functions にトリガー関数を追加する #

公式ドキュメントの以下を実施します。

functions/index.js ファイル内のコードを次のコードで置き換えます。

自分が扱いやすいようにアレンジしたサンプルが以下です。

import functions, { logger } from 'firebase-functions';
import firestore from '@google-cloud/firestore';

const { pubsub } = functions.region('asia-northeast1');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://***(backet-name)***';

export const scheduledFirestoreExport = pubsub
  .schedule('0 0 * * 0')
  .timeZone('Asia/Tokyo')
  .onRun(async (_) => {
    const projectId = (process.env.GCP_PROJECT || process.env.GCLOUD_PROJECT) as string;
    const databaseName = client.databasePath(projectId, '(default)');

    try {
      const responses = await client.exportDocuments({
        name: databaseName,
        outputUriPrefix: bucket,
        collectionIds: [],
      });
      const response = responses[0];
      logger.info(`Operation Name: ${response['name']}`);
    } catch (e) {
      logger.error(e);
      throw new Error('Export operation failed');
    }
  });

4. 作成した関数をデプロイする #

公式ドキュメントの以下を実施します。

スケジュール設定された関数をデプロイします。

(もしすでに他の関数も存在しているならば、それらの関数までまとめて全部をデプロイする必要はありませんので)今回作成した関数のみをデプロイするために以下コマンドで実施します。

firebase deploy --force --only functions:scheduledFirestoreExport

5. サービスアカウントに権限を付与する #

デプロイした関数を実行するユーザに、Firestore からのエクスポート処理および Cloud Storage への書き込み処理の実行に必要な権限を付与します。

公式ドキュメントの以下を実施します。

Cloud Datastore インポート / エクスポート管理者ロールを割り当てます。

gcloud projects add-iam-policy-binding ***PROJECT_ID*** \
    --member serviceAccount:***PROJECT_ID***@appspot.gserviceaccount.com \
    --role roles/datastore.importExportAdmin
  • ***PROJECT_ID*** の部分は自分の Firebase プロジェクトの ID に置き換えます

バケットに対するストレージ管理者ロールを割り当てます。

gsutil iam ch serviceAccount:***PROJECT_ID***@appspot.gserviceaccount.com:admin \
    gs://***BUCKET_NAME***
  • ***PROJECT_ID*** の部分は自分の Firebase プロジェクトの ID に置き換えます
  • ***BUCKET_NAME*** の部分は自分の Cloud Storage の バケット名に置き換えます

6. 関数が機能することをテストする #

ここまででバックアップ処理が動くようになっています。指定したスケジュールを待たず、機能することをいますぐに確かめたい場合は、公式ドキュメントの以下を実施してください。

Cloud Scheduler ジョブと Cloud Functions の関数をテストする

参考 #