MinecraftのWorldsのBackupを取得する
Intro
Cloud上のDocker内で稼働しているMinecraftのワールドの増分バックアップをNASに保存し続けたい。
TL; DR
- Docker内のワールドデータをDocker外にコピーする
- Docker外のワールドデータをNASにコピーする
- 増分バックアップを行う
サーバー環境
まず、該当のマイクラサーバーの環境を確認する。
| Key | Value |
|---|---|
| Minecraft Version | Bedrock |
| Platform | Cloud Server |
| OS | Ubuntu 22.04 LTS |
| App | Docker |
| Docker Image | itzg/minecraft-bedrock-server |
さらに、マイクラ鯖へはsshにてアクセスできる。
鯖は毎日稼働しているとは限らず、同時にWorldデータが毎日更新されるとも限らない。
(マイクラを遊ぶ頻度はそれほど高くない。ただし、一定期間では数日間連続で遊ぶことで、ワールドデータが大幅に更新されるかもしれない。)
NASは常時稼働しており、Linux likeなOSを搭載している。
あくまでLinux likeなので、Linuxのすべてを兼ね備えているわけではないが、主要なコマンドは搭載されている。
バックアップ方針
以下にバックアップに関する前提を記載する。
- バックアップデータはNASに保存する
- 1GBを超えないことが見込める以上、Google Driveなどでもよかったかもしれない
- マイクラ鯖の停止中にもバックアップにアクセスしたいので、マイクラ鯖と同じServer上に保存するのは避ける
- バックアップシステムはNAS上で稼働すると簡単
- 今回に限ってはマイクラ鯖と同じServer上で稼働させてもよいか
- 増分バックアップ方式を採用する
- マイクラのワールドデータは平常時はDocker Volume内に存在している点に注意する
当初は、Smart Cycle Backup (新しいバックアップは密に、古いものは疎になるように)によって、
保存するバージョン数を抑制しながら、全期間のデータを保持することも方針に含めていた。
しかし、マイクラのワールドデータはたかだか数百MB程度であり、増分バックアップで全期間保存しても問題ないことが判明してしまった。Smart Cycle Backupのアルゴリズムまで考えていたのに……。
思うに、Smart Cycle Backupは、差分バックアップやフルバックアップの保持に特に適しているだろう。
保存容量が数十程度は見込めつつ、数千は難しい場合に適する。
実装
to Docker外
まず、Docker Volume内にあっては外部からアクセスしづらいので、一度Docker外にワールドデータをコピーする。
1 | |
このShell ScriptはDOCKER_ROOT/scriptに存在している。
(docker-compose.ymlはDOCKER_ROOT直下に配置されている)

このScriptは、最小の頻度ならばバックアップを取得するたびに、最大の頻度ならば毎日定時に実行される。
バックアップするシステムとして何らかのアプリケーションを利用する場合、
稼働時にssh先のScriptを実行するのは難しいので、Server側で定時実行することになる。
(この場合、定期実行の時間の設定がバックアップシステム側とServer側の両方に存在するのが少しだけ面倒)
今回はDockerコンテナを前提にしているので考慮する必要もなかったが、
Docker Volume内のデータを外部にコピーする方法は、過去記事を参照。
上記Scriptでは、$(cd $(dirname $0); pwd)/..で、Scriptの絶対pathの親ディレクトリを取得している。
まず$0で呼び出されたScriptのpathを取得する。
これは呼び出され方に応じた値が入る。相対pathであったり、絶対pathであったりする。
次にdirnameでpathのディレクトリ部分を取得する。$0がscript/tmp.shの場合、dirname $0はscriptになる。script内で./tmp.shとして実行していた場合、dirname $0は.になる。
そしてscript内でbash tmp.shとして実行していた場合、dirname $0は(空文字)になる。
もうお気付きだろう。
最後のケースに$(dirname $0)/..とすると、これは/..になり、結果として/とみなされる。
ただ実行ファイルの親ディレクトリに移動したかっただけなのに、Rootディレクトリに対して操作する羽目になるのだ。あぶない!!
$(cd $(dirname $0); pwd)とすると、sub shell内でdirname $0の結果に対してcdを実行し、その後pwdで絶対pathを取得する。
これで、Scriptのフォルダの絶対pathを取得できる。
つまり、(Script自体がRootに置かれていない限り)$(cd $(dirname $0); pwd)/..で安全に親ディレクトリを取得できるというわけだ。
to NAS
ServerからNASへのバックアップは、rsyncを利用する。
1 | |
まずはじめにsshでServerに接続し、minecraftWorldsCopyFromDocker.shを実行する。
ここでエラーが生じた場合は、バックアップを取得できないので、Scriptを終了する。
続いて、マイクラのワールドデータをまるごとNASの仮置き場にコピーする。
バックアップ対象のワールドごとに、最新のデータをdata/$worldName/latest/data/にコピーする。
さらに、そのワールドの最終更新日時をCURRENTから取得し、data/$worldName/latest/dt.datに記録する。
ついでにdocker-compose.ymlやscriptもバックアップすることにした。
増分バックアップ
1 | |
保存済みの最新アーカイブを取得し、それをもとに増分バックアップを行う。
最新アーカイブが存在しない場合は、全データをコピーする。
最新アーカイブと取得データの日時が一致する場合は、変更がないと判断し、何もしない。
SUSEのドキュメントによると、~/binにユーザーが作成したScriptを保管するのが推奨されるそうだ。
/usr/local/binのようなユーザーフォルダ外部にScriptを補完するのは不安になるので、これはうれしい。
ただ、cronに実行する場合など、トリガーがUserに依存しない場合は、
ユーザーフォルダ内部でない方が自然な気がしないでもない。
定期実行
Server側で定期実行するために、crontabを利用する。sudo crontab -eで設定ファイルを開き、以下のように記述する。
下記では毎週日曜日、月曜日、水曜日、土曜日の3時にバックアップを取得する。
1 | |
Future Work
- バックアップデータの保存先をGoogle Driveなどに変更する
- あるいは、Google Driveに抽出したバックアップを保存する
- 定期的にFull Backupを取得することで、古いデータが破損した場合の影響を抑制する
- ScriptをGitHubで公開する
- できれば、Smart Cycle Backupのアルゴリズムも実装したいなぁ
- Google DriveにExportする場合と組み合わせればよいか?
- 直接は関係ないけど、docker-compose.ymlもバックアップすべきか
まとめ
マイクラのワールドデータのバックアップをNASに保存する方法を記載した。
NASに保存することで、マイクラ鯖の停止中にもバックアップにアクセスできるようになる。
また、増分バックアップを採用することで、バックアップデータの保存容量を抑制しつつ、全期間のデータを保持することができる。





