DockerとData Volume Containerのお話


## 註記 (2018/03/22)
この記事を書いてから長い月日が経ちましたが、じわじわといいねを頂いているようで…ありがとうございます。

ただ…正直この記事の内容はすでに太古の手法と化しています。

今のDockerではvolume機能を用いれば、ここに書かれた例のようにわざわざデータ永続化のためだけにコンテナを用意する必要も無くなります。
docker-composeであればデフォルトではvolumeのみ削除しない仕様なので、うっかりvolumeを闇に葬り去るという悲しい事件を起こしてしまうことも防げると思いますし、こちらを活用したほうが良いと思います。

詳細は気が向いたら書こうかと思います…書けたらいいな…

## Dockerコンテナはデータを保持できない
DockerでMySQLなどのデータベースサーバを運用する場合、データの永続化が問題になります。
Dockerはコンテナを削除すると、保存されたデータが全て消えてしまうためです。

## 永続化のためにコンテナを作る
データを格納するためだけのData Volume Container（以下ストレージコンテナ）を作成します。

### コマンド

```bash
$ docker run -d -v /dir/of/data --name storage busybox true
```

#### オプションの意味

- `-d` -> コンテナをバックグラウンドで実行する
- `-v /dir/of/data` -> ホストにマウントするディレクトリを指定。
	- この場合コンテナ側のパスのみを指定しているので、ホスト側の`/dir/of/data`は関係がない。
	- 例）MySQLのデータディレクトリの場合は、`/var/lib/mysql`
- `--name storage` -> ストレージコンテナの名前を指定。既存のコンテナと違う名前（ユニーク）なら自由に指定出来る。
- `busybox` -> 使用するイメージ名。
	- `ubuntu`でも何でもいいが、`busybox`は軽量なのでこういう用途にはよく使われる（らしい？）
- `true` -> `busybox`イメージ内で実行するコマンド。
	- ストレージコンテナはコンテナとして存在しているだけで良いので、何もせずに正常終了する`true`コマンドを使用する。

## ストレージコンテナを利用するコンテナを作成する
例としてMySQLコンテナを使ってみます。

### コマンド

```bash
$ docker run -d --volumes-from storage -e MYSQL_ROOT_PASSWORD=root --name mysql_server mysql
```

#### オプションの意味

- `-d` -> 同上。
- `--volumes-from storage` -> 先ほど作成したストレージコンテナを指定。これから作成するコンテナにストレージコンテナのディレクトリをマウントする。
- `-e MYSQL_ROOT_PASSWORD=root` -> mysqlイメージで必須のオプション。rootのパスワードを設定します。もちろんrootの部分はお好みで。
- `--name mysql_server` -> 同上。
- `mysql` -> `mysql`イメージを選択。Dockerは公式でMySQLのイメージがリリースされているようで、こう叩くだけでそのまま使い始められます。すごい。

### 設定ファイルを追加する

DockerのMySQLイメージは、デフォルトで`Server Charset`と`Db Charset`が`latin1`になっています。
全部utf8じゃないと気持ち悪い奇病に罹っているの状態の私のように、文字コードなど、設定をいじりたい場合があります。

その場合、ホスト側にある設定ファイルをコンテナの`/etc/mysql/conf.d`にマウントしてやればOKです。

#### コマンド

```bash
$ docker run -d --volumes-from storage -v /path/of/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root --name mysql_server mysql
```

#### オプションの意味（重複は割愛）
- `-v /path/of/conf:/etc/mysql/conf.d` -> ホスト側の`/path/of/conf`をコンテナの`/etc/mysql/conf.d`にマウントします。
	- こうすることで、ホスト側の`/path/of/conf`の中に`custom.cnf`などを書いておけば、コンテナのMySQLはこれも読みに来てくれます。
	- オプションの並び順ですが、イメージ名の前ならば順番は問いません。


## しかしsaveやexportしてもデータは消える！！
さて、これでストレージコンテナが出来たから、`docker save`や`docker export`でデータが持ち運べるゾ〜
と思っていた時期もありました。

なんと、【消えます】。

いくらストレージコンテナといえど、コンテナやイメージのアーカイブにデータは格納されないようです。

それに対し、Dockerの公式ページや、他の方の投稿で多く示されていた方法があったので、それを参考にしました。

### バックアップ

```bash
$ docker run --rm --volumes-from storage -v $(pwd):/backup busybox tar cvf /backup/backup.tar /dir/of/data
```

#### オプションの意味
- `--rm` -> コンテナのプロセスが終了すると、すぐにコンテナが削除されます。
	- 今回はtarコマンドでアーカイブをするためだけにコンテナを作成するので、それが終われば即・お役御免、ということですね。作られては消される、というのはDockerコンテナの性（さが）でしょうか。
- `--volumes-from storage` -> 同上。
- `-v $(pwd):/backup` -> 現在の作業ディレクトリを、コンテナ側の`/backup`にマウントします。
	- `pwd`は現在の作業ディレクトリを出力するコマンドです。
- `busybox` -> イメージ名
- `tar cvf /backup/backup.tar /dir/of/data` -> コンテナで実行するコマンド。
	- コンテナ内の`/dir/of/data`をアーカイブし、コンテナの`/backup`内に`backup.tar`として保存します。
		- MySQLのデータディレクトリなら`/var/lib/mysql`です。
	- コンテナの`/backup`には上記の通りホストの現在の作業ディレクトリがマウントされているので、ホストの作業ディレクトリにも`backup.tar`が保存されます。
	- `tar`コマンドのオプションを`zcvf`に、出力ファイル名の拡張子を`.tar.gz`にすると、アーカイブに加えて圧縮をかけることが出来ます。

### 復元

```bash
$ docker run --rm --volumes-from new_storage -v $(pwd):/backup busybox cd /dir/of/data && tar xvf /backup/backup.tar
```

#### オプションの意味（重複は割愛）
- `--volumes-from new_storage` -> マウントするディレクトリを格納したコンテナ…つまりは、復元するストレージコンテナを指定。
- `cd /dir/of/data && tar xvf /backup/backup.tar` -> コンテナ内の復元先のディレクトリに移動してから、アーカイブを展開する。

### つまり・・・どういうことだってばよ？
ストレージコンテナの中身をディレクトリごとアーカイブして外に出してるだけ！

＿人人人人人人人人人人人＿
＞　最早Docker関係ない　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣

しかし、公式サイトにもあるくらいなのでこれが正統なのです。Dockerは「環境を持ち運ぶもの」と考えて、「データを持ち運ぶものではない」と思って使うと、幸せになれるかもしれません。

## 参考にさせていただいた記事
- Managing data in containers  
  [https://docs.docker.com/userguide/dockervolumes/](https://docs.docker.com/userguide/dockervolumes/)
- Docker × MySQL  
  [http://qiita.com/baster/items/32a66766cbfd28e63a6b](http://qiita.com/baster/items/32a66766cbfd28e63a6b)
- Dockerのbusyboxは永続コンテナと言いながらexport/saveコマンドでは持ち運びできないよ  
  [http://qiita.com/kumechang/items/fc108b1ec4683f3765d8](http://qiita.com/kumechang/items/fc108b1ec4683f3765d8)
- DockerでMySQLを動かす(気を付けるべきところとかいろいろ)  
  [http://qiita.com/TakamiChie/items/a7437b1a24961ba9c83e](http://qiita.com/TakamiChie/items/a7437b1a24961ba9c83e)

## 追記 2015-09-19 4:08
- tarコマンドの箇所ですが、`busybox`に入っている`tar`コマンドはzオプションをつけてgzip圧縮をするのに対応していないようです。`busybox`の代わりに`ubuntu`などを指定するとzオプションでgzip圧縮がかけられます。