社内でGrowiを立ち上げてみた（補足その3）

# はじめに

https://qiita.com/cohpen/items/d307dfb8b540e3976d37

で運用を始めたGrowiですが、折角蓄積したデータを失うと大変ですのでバックアップを取ることにしました。また、バックアップからデータを復元する手順も練習して、安定した運用ができるようにしました。

公式で用意されているmongoDBデータのバックアップは下記ですが、
 
https://docs.growi.org/ja/admin-guide/admin-cookbook/mongodb-backup-regular.html#%E5%89%8D%E6%8F%90%E6%9D%A1%E4%BB%B6

https://docs.growi.org/ja/admin-guide/admin-cookbook/mongodb-backup.html#%E6%A6%82%E8%A6%81

どちらもAWS S3へのバックアップが前提で手が出ません。<del>（この富豪どもめ）</del>

また、Growi自身の機能のデータのアーカイブ・インポートは、Growiのバージョンが全く同じでないとダメで正直<del>使い物にならない</del>使い勝手が悪いです。（一度やってみたら、インポート先で立てたGrowiがマイナーバージョンが上がっていてインポートできなかった。使えねー）

https://docs.growi.org/ja/admin-guide/management-cookbook/export.html

# バックアップ手順
自分の部署ではアップロードファイルもmongoDBに保存しています。なのでmongoDBのデータベースをまるっとコピーすればバックアップ完了です。
もし、アップロードファイルをローカルに保存する設定で運用している場合はそちらもケアが必要と思います。

mongoDBデータの保存手順を簡単に説明します。
- monogoDBのコンテナ内でmongodumpコマンドを起動してバックアップデータを作成する
- monogoDBコンテナ内からバックアップデータを取り出す
- 上記バックアップ手順を自動化する

本来、バックアップデータを取る前にはGrowiをメンテナンスモードにしてユーザがデータ更新できない状態にするべきですが、自分の部署では夜中にアクセスするユーザはいませんのでGrowiは通常動作のままで夜中にバックアップのスクリプトを走らせることでよしとしました。

なお、docker-compose stopでGrowiを止めてしまうと、mongoDBコンテナの実行が止まってデータを取り出せなくなります。Growiは実行状態でないとダメです。
## mongodumpでバックアップデータを作成する
mongoDBのコンテナ内でmongodumpコマンドを実行することで、DBを一つのファイルにまとめます。
mongoDBのコンテナ名を確認
```
$ cd /opt/growi
$ sudo docker-compose ps
```
で表示されるmongoDBのコンテナ名（growi_mongo_1、あるいはgrowi-mongo-1とかのはず)を使ってmongodumpコマンドでmongodb.archiveというファイルにダンプします。
docker exec コンテナ名 コマンド
で起動中のコンテナ内でコマンドを実行することができます。
```
$ sudo docker exec growi_mongo_1 mongodump --archive=mongodb.archive
```
mongodb.archiveというファイルがルートディレクトリにできているはずです。

[余談] mongodumpを説明しているBlogで、docker execに-dオプションをつけている例が見受けられます。
$ sudo docker exec -d growi_mongo_1 mongodump --archive=mongodb.archive
-dオプションをつけるとmongodumpがバックグラウンドで実行されるのでいつ終了したかわかりません。手打ちでコマンドを入れている場合は次のdocker cpを実行する前に動作が完了しているかも知れませんが、シェルスクリプトで連続実行する場合、mongodumpが終わる前にdocker cpが実行されてしまう事故が起きます。-dオプションでデタッチ実行せず、mongodumpのメッセージ表示を止めたい場合は--quietオプション
$ sudo docker exec growi_mongo_1 mongodump --archive=mongodb.archive --quiet
でどうぞ。
mongodumpが作ったmongodb.archiveファイルは
```
$ sudo docker exec growi_mongo_1 ls -l
```
で表示して確認することができます。
## コンテナからの取り出し
コンテナの中から外のファイルシステムにファイルをコピーするには
docker cp コンテナ名:元ファイル名 コピー先ファイル名
で行います。逆に外のファイルをコンテナ内にコピーすることもできます（リストア手順で使用）
```
$ sudo docker cp growi_mongo_1:/mongodb.archive mongodb.archive.bak
$ ls -l
```
カレントディレクトリにmongodb.archive.bakが取り出せていると思います。
## バックアップの自動化
mongoDBのデータの取り出し、バックアップデータの一定期間保存についてこちらのスクリプトを参考にさせていただきました。
[補足] ファイル名には日時だけでなく、実行中のGrowiのバージョンとmongoDBのバージョンも加えておくことをお勧めします。
yyyymmddhhmm-growi6.3-mongo6.0-mongodb.archive とか

https://zenn.dev/nekoniki/articles/042bb1790b222c

# リストア手順
[重要] リストア先のmongoDBは、バックアップを取ったmongoDBと同じバージョンでなければなりません。新規にGrowiを立て直す場合はmongoDBのバージョンが変わってないことを確認してください。もし違っていたら、バックアップ時のmongoDBバージョンを指定してGrowiを立ち上げること。

以下の手順でバックアップデータをGrowiにリストアすることができます。
- 空のGrowiを起動します
- バックアップデータをmongoDBコンテナ内にコピーします
- mongorestoreでmongoDBにデータをリストアします
- Growiの検索インデックスをリビルドします
## 空のGrowiの起動
新規にGrowiを起動する場合はこの作業は不要です。
また既存のGrowiのデータを消去せずに上書きすることもできるようです。（後述）

既存のGrowiのデータを消去するには、
- コンテナ停止
- コンテナ消去
- イメージ消去
の手順を踏みます。実行中のコンテナは消去できない、コンテナが使用しているイメージは消去できない、という仕組みです。

https://www.kagoya.jp/howto/cloud/container/dockerimagedelete/

イレギュラーな操作をして残ってしまったイメージは強制的に消去するのに苦労することが...

```
$ sudo docker images -a
```
ですっかりイメージが空になったことが確認できたら、
```
$ cd /opt/growi
$ sudo docker-compose up -d
```
で空のGrowiを起動します。
## バックアップデータをmongoDBコンテナ内にコピー
カレントディレクトリにmongodb.archive.bakというバックアップファイルがあるとします。これをdocker cpコマンドでmongoDBのコンテナ内にコピーします。
```
$ sudo docker cp mongodb.archive.bak growi_mongo_1:/mongodb.archive
$ sudo docker exec growi_mongo_1 ls -l
```
/mongodb.archive というファイルができているはずです。（サイズがおかしくないかチェック）
## バックアップデータのmongoDBへのリストア
mongoDBコンテナ内でmongorestoreコマンドを実行してバックアップデータからリストアします。
```
$ sudo docker exec growi_mongo_1 mongorestore --archive=mongodb.archive
```
これでGrowiにログインすると、データが復活しているはずです。
ここでmongorestoreのオプションに--dropをつけると、既存のデータベースが残っている状態でも上書きしてリストアすることができるそうです。
## 検索インデックスのリビルド
mongoDBをリストアするとインデックスの整合性が取れていないのでGrowiの検索が機能しません。公式ドキュメントにあるようにGrowiに管理者ログインしてインデックスのリビルドを実行してください。

https://docs.growi.org/ja/admin-guide/management-cookbook/setup-search-system.html#%E3%82%A4%E3%83%B3%E3%83%86%E3%82%99%E3%83%83%E3%82%AF%E3%82%B9%E3%81%AE%E3%83%AA%E3%83%92%E3%82%99%E3%83%AB%E3%83%88%E3%82%99

補足：Growi 6.2.xからGrowi 7.2.2へ上記の手順でmongoDB 6.0のデータをインポートしたところ、インデックスのリビルドがなぜかうまくできませんでした。（検索してもほとんどヒットしない）
一度、
$ cd /opt/growi
$ sudo docker-compose down
でコンテナを消去してから、
$ sudo docker-compose up -d
で再構築したところ、リビルドできるようになりました。（コンテナを消去してもmongoDBのデータは消えない）
なおインポートしたデータからは編集履歴が消えていました。同じmongoDB6.0同士のインポートでも、Growiのバージョンも揃えておいた方が良かったのかもしれません。