🗂

Firestoreを定期的にバックアップする拡張を公開しました

2023/06/09に公開
3
CHANGELOG

背景

Firestore ドキュメントのバックアップには exportDocuments API が提供されており、gcloud コマンドを利用してエクスポートが可能です。実際、上記 API 叩く Cloud Scheduler ジョブを作成し、定期的にバックアップをとる公式の Cookbook や先人たちの記事が存在します。

https://firebase.google.com/docs/firestore/solutions/schedule-export?hl=ja

これでも十分楽なのですが、gcloud コマンドや Cloud Schedular、 API を叩く処理、サービスアカウントの生成などセットアップまでの準備が少し手間です。Firestore の定期的なバックアップは 「万が一のために必要な機能だが利用するシーンは稀」 な最たる例だと思いますし、可能な限り手間なく・爆速にセットアップできたら嬉しいですよね。

というわけで、今回はこれらの手順をラップした Firebase Extensions として back-up-firestore-to-storage を Extensions Hub に公開しましたので、これを使ってさらにお手軽にセットアップする手順をご紹介します。

Back up Firestore to Storage

拡張は以下を使用します[1]

https://extensions.dev/extensions/htsuruo/back-up-firestore-to-storage

1つ重要な注意点があり、エクスポートする際に対象となるドキュメントを READ する形になるので、その分のコストがかかります。

Caution: Exporting data from Cloud Firestore will incur one read operation per document exported. However, these reads will not appear in the usage section of the console. Make sure you understand this before setting up recurring exports to avoid an unexpected bill.

特徴

この拡張の主な特徴は以下の3点です。

  • 指定したコレクション ID のドキュメントをバックアップ
    • 例えば、users,posts とカンマ区切りで指定すれば、usersposts コレクションのドキュメントがエクスポートされます(それ以外のドキュメントはエクスポートされません)。
    • 未指定の場合はすべてのコレクション(=すべてのドキュメント)がエクスポートされます。
    • 前述した READ コストの兼ね合いで選ぶと良いです。
  • バックアップのタイミングを任意に指定
    • Unix CrontabApp Engine syntax の両方のシンタックスに対応しています。
      • 例1)毎日0:00にバックアップ: every day 0:00
      • 例2)毎月1日(月初)にバックアップ: 0 0 1 * *
  • タイムゾーンの指定
    • Asia/Tokyo と指定すれば日本時間で実行され、エクスポートされるフォルダも日本時間となります。
      • exportDocuments を使用するだけではタイムゾーンを指定しても出力されるフォルダは UTC 時間になってしまいます。

セットアップ手順

セットアップは拡張をインストールするだけです。コマンドポチポチで完結します。

1. 拡張をインストール

以下から「Install in Firebase console」ボタンを押下し、Firebase プロジェクトにインストールします。

https://extensions.dev/extensions/htsuruo/back-up-firestore-to-storage

2. 拡張機能を構成

以下の必要な項目を入力します。インストールして後は指定したスケジューラで実行されるのを待つだけです。

バケットについて

バケットが未指定の場合はデフォルトで [project_id].appspot.com が利用されますが、事前にバックアップ用のバケットを Coldline または Archive ストレージクラスで作成しておき、指定するのがおすすめです。バケットが存在しない場合はエラーとなりますので、事前に Google Cloud Console 上で作成が必要です。

ストレージクラスは可用性や保存時の料金に違いがあります。本ユースケースではバックアップ用途で参照する機会は稀だと思いますので、一般的には上記のストレージクラスが適していると思いますが、サービス要件に合わせて適宜ご判断ください。他にもライフサイクルや保持期間などの設定ができますので、適宜要件に合わせて設定してください。

https://cloud.google.com/storage/docs/storage-classes#classes

例: 日本時間の毎日0:00に users ドキュメントを htsuruo-firestore-backup バケットへバックアップする

Cloud Storage bucket: htsuruo-firestore-backup
Cloud Storage prefix path:
Firestore collection ids: users
The frequency at which you want to execute the backup: every day 0:00
The time zone in which the schedule will run (Defaults to UTC): Asia/Tokyo
Cloud Functions location: asia-northeast1

サブコレクションについて

exportDocuments の仕様に準拠しておりますので、サブコレクションも同様にエクスポートが可能です。コレクション ID が未指定の場合は、他コレクション同様にエクスポートされます。コレクション ID を指定する場合はルートコレクションの記述は不要です。

例)users ドキュメントの followers サブコレクションをエクスポート指定する場合

- OK: followers
- NG: users/followers

サブコレクションといっても見た目上階層構造に区切られているだけで、ルートコレクションと性質自体はあまり変わりません。ですので、他コレクションと同様にエクスポートが可能なのだと理解しています。
ちなみに、エクスポート時のメタデータに「サブコレクションである」という情報も一緒に出力されますので、インポート時にも正確にサブコレクションとして復元されます。

3. バックアップを確認

スケジュールされた時間になったらバックアップされていることを確認します。出力形式は exportDocumentsAPI を利用した場合と同じですので、そのままインポートできます。

インポートを確認

インポート(リストア)方法については、Import all documents from an export をご参照ください。インポートが必要な機会は稀だと思いますので、その場合は gcloud コマンドで実行してください(本拡張はエクスポートのみの対応です)。正常にインポートされるとコンソールに以下のような出力がされるはずです。

❯ gcloud firestore import gs://htsuruo-firestore-backup/2023-06-11T14:30:00_549
Waiting for [projects/[PROJECT_ID]/databases/(default)/operations/AiAyMDQwNTU4NTUJGnRsdWFmZWQHEjF0c2FlaHRyb24tYWlzYS1zYm9qLW5
pbWRhGgoyEg] to finish...done.
metadata:
  '@type': type.googleapis.com/google.firestore.admin.v1.ImportDocumentsMetadata
  inputUriPrefix: gs://htsuruo-firestore-backup/2023-06-11T14:30:00_549
  operationState: PROCESSING
  startTime: '2023-06-11T05:42:46.574762Z'
name: projects/[PROJECT_ID]/databases/(default)/operations/AiAyMDQwNTU4NTUJGnRsdWFmZWQHEjF0c2FlaHRyb24tYWlzYS1zYm9qLW5pbWRhGgoyEg

まとめ

Firebase Extensions を利用すると、プロジェクト側で Cloud Functions を立ち上げる必要無いですし、適宜必要なサービスアカウントまで自動で作成してくれるので、お手軽にセットアップできておすすめです。特に今回の定期バックアップのような、プロジェクト立ち上げ時にほぼ必須となる機能を毎回 Functions で用意するのは面倒だと思うので、Extensions Hub で公開しておくと再利用できて楽になると思います。

Firebase Extensions の開発方法や Extensions Hub への公開方法については、以下の記事で紹介していますので、ぜひご参照ください。
https://zenn.dev/tsuruo/articles/34f1683779d3ae

参考

脚注
  1. Firebase Extensions の使用には Blaze プラン の契約が必要です。 ↩︎

Discussion

BarleyBarley

素晴らしい👏👏👏是非使わせて頂きます。

(試してみればいい話なのですが🙏🏻)サブコレクションやカスタムインデックスもエクスポートしてくれるものでしょうか?

ツルオカツルオカ

コメントいただきありがとうございます。

サブコレクションやカスタムインデックスもエクスポートしてくれるものでしょうか?

サブコレクションについてはエクスポート可能です。詳細については追記いたしましたのでご参照ください。

カスタムインデックスについては、本拡張はコレクション(及びドキュメント)のみが対象なためエクスポートされません。
インデックスについては、Firebase CLIでエクスポート・デプロイできますのでそちらを利用すると良いと思います(セキュリティルールも同様)。

https://firebase.google.com/docs/reference/firestore/indexes

# Export
firebase firestore:indexes > firestore.indexes.json

# Deploy
firebase deploy --only firestore:indexes
BarleyBarley

丁寧なご返事ありがとうございます🙏🏻

(そうですね、セキュリティルールもありますね😅)