dockerのデータボリュームとそのバックアップ方法


データの永続化はdockerでよく課題になると思います。
docker docsには、Manage data in containersの節に、いくつかの方法が示されています。

  • データボリュームを利用する
  • ホストのディレクトリにマウントする。

しばらく前まではホストのディレクトリに逃がしていたのですが、ホストのディレクトリとコンテナの中ではユーザの番号や書き込み権限の管理が違ったりして、うまくいかないことも多かったので、最近はまじめにデータボリュームを使うようにしています。

MySQLを例に、データボリュームとそのバックアップ方法をまとめてみます。

データボリュームを作成してマウントする

データボリュームは、dockerfileのVOLUMEで指定したディレクトリ、またはdocker runにて-vで指定したディレクトリに、自動で作られます。そしてそれは、コンテナとは別に管理され、docker commitdocker exportしてもデータボリュームの内容は含まれません。コンテナ間のデータ共有は、データボリュームによってのみ可能です。

イメージ

自動で作られるだけではなく、コマンドで作ることもできます。MySQLのデータを管理するデータボリューム作ってみます。
このデータボリュームの名前をmysql_dataとします。

docker volume create --name mysql_data

データボリュームのリストは、コマンドで確認できます。

docker volume ls
DRIVER              VOLUME NAME
local               mysql_data

では、MySQLのコンテナにこのデータボリュームをマウントさせます。

docker run -d --name mysql -p 3306:3306 -v mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql

確かに、マウントされていることが、docker inspectで確認できます。

docker inspect mysql

    ...

    "Mounts": [
        {
            "Name": "mysql_data",
            "Source": "/mnt/sda1/var/lib/docker/volumes/mysql_data/_data",
            "Destination": "/var/lib/mysql",
            "Driver": "local",
            "Mode": "z",
            "RW": true
        }
    ],

    ...
なお、データボリュームはcreateすることができますが、標準の`local`の場合、一度コンテナに紐付けられると、そのコンテナが破棄された時にデータボリュームも一緒に破棄されます。よって、データボリュームを作成するときは、busyboxなどのコンテナにわかりやすい名前で紐つけておいたほうが良いと思われます。
docker create --name mysql_data -v mysql_data:/var/lib/mysql busybox

(2015/12/09追記)確認しました。基本的にデータボリュームはコンテナを消しても削除されません。--rmをオプションにつけると、コンテナと一緒にデータボリュームを消す機能があるようです。

データボリュームのバックアップ

コンテナやイメージと違い、データボリュームは単体でバックアップする方法は提供されていないようでした。このデータボリュームはプラグイン化されており、docker volume create -d [plugin]で指定できます。きっとバックアップは各プラグインで考えることなのだろうと思います。

ちなみに、上記のdocker inspectの結果localと書かれていますが、実はSourceのディレクトリがマウントされているだけです。バックアップには、このディレクトリを直接処理しても良いと思います。

よく登場するのは、他のコンテナにこのデータボリュームをマウントし、そこでバックアップをする方法です。なんだかなーとおもって、データバックアップ専用のコンテナ74th/volumebackupを作成しました。

https://hub.docker.com/r/74th/volumebackup/
https://hub.docker.com/r/74th/volumerestore/

以下のコマンドを実行すると、mysql_data-YYYYMMDDHHmmss.tar.gzというファイルにバックアップします。

docker run -v mysql_data:/target -v `pwd`:/export -e NAME=mysql_data 74th/volumebackup

復元するには、復元用コンテナを使います

docker volume create --name mysql_data2
docker run -v mysql_data2:/target -v `pwd`:/import -e TARGETFILE=mysql_data-20151206124353.tar.gz 74th/volumerestore

最後に、このバックアップが使えることを確認します。

docker run -d --name mysql2 -p 3306:3306 -v mysql_data2:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql

おわり

dockerは正義!なツールを発表しようと思っていましたが、まだ未熟なツールなので、ちゃんと理解していなかったデータボリュームについてまとめました。

https://github.com/74th/flyingwhale