Docker コンテナ内でのデータ管理

オリジナルは以下のサイトです。訳しながら実際に試したメモになります。
https://docs.docker.com/userguide/dockervolumes/

本章では、どのようにDockerコンテナ間やコンテナ内のデータを管理するかについて記載する。Docker 上のデータ管理として「データボリューム」と「データボリュームコンテナ」の２つがある。

確認作業を行った際のDockerのバージョンは以下のとおりです。

```
# docker version
Client:
 Version:      1.8.0
 API version:  1.20
 Go version:   go1.4.2
 Git commit:   0d03096
 Built:        Tue Aug 11 16:43:14 UTC 2015
 OS/Arch:      linux/amd64
Server:
 Version:      1.8.0
 API version:  1.20
 Go version:   go1.4.2
 Git commit:   0d03096
 Built:        Tue Aug 11 16:43:14 UTC 2015
 OS/Arch:      linux/amd64
```

# 1. データボリューム
データボリュームは、ユニオンファイルシステムをバイパスする1つまたは複数のコンテナ内にある、特別に指定されたディレクトリである。データボリュームは永続的なデータや共有データに対して便利な機能を提供する。
>ユニオンファイルシステムは、異なるファイルシステムのファイルやディレクトリを透過的に重ねて、ひとつのファイルツリーを構成できるファイルシステム。LIVE CDで使われており、CD-ROMに記録してあるOS部分をreadonlyとして利用し、メモリ空間にwritableなfile systemを用意して、それを重ねあわせる。ファイルシステムに変更があった場合はメモリ空間の方を変更して、書き込みができているように見せている。

・ボリュームはコンテナが作られるときに初期化される。もしコンテナのベースイメージがデータを含んでいる場合、既に存在するデータは新しいボリュームにコピーされる。
・データボリュームはコンテナを跨いで共有及び再利用可能である
・データボリュームへの変更は直接可能である
・データボリュームへの変更はイメージのアップデートに含まれない
・コンテナ自身が消えてもデータボリュームは消えない
※AWSのEBS、OpenStackのCinderのような感じかな？

データボリュームはコンテナのライフサイクルとは独立した永続的なデータとしてデザインされている。それゆえコンテナが削除されたりしても、Dockerは自動的にボリュームを消すといったことはしない。

#### 1.1. データボリュームの追加
docker createやdocker runを実行するときに、-vフラグを使用することでデータボリュームを追加することができる。-vを複数回使用すると、複数のデータボリュームを追加できる。

以下のコマンドを実行するとコンテナ内に/webappというボリュームが追加される。※dockerfileに記述する場合はVOLUMEで指定。

```
# docker run -t -i --name web -v /webapp training/webapp /bin/bash
root@0684c34ec88b:/opt/webapp# df -h |grep /webapp
/dev/mapper/centos-root                                                                              118G   16G  102G  14% /webapp
```
デフォルトではread-writeだが、以下のようにread onlyなどを設定することも可能

```
# docker run -d -P --name web -v /opt/webapp:ro training/webapp python app.py
```

#### 1.2. ボリュームの場所
docker inspectコマンドで実際にどの領域がマウントされているか確認することができる。

```
# docker inspect web
・・・
    "Mounts": [
        {
            "Name": "df55bb4bfe1218c6a222df6917d177cf4dc22849ef5ebc6b4c8483a1a2abdf41",
            "Source": "/var/lib/docker/volumes/df55bb4bfe1218c6a222df6917d177cf4dc22849ef5ebc6b4c8483a1a2abdf41/_data",
            "Destination": "/webapp",
            "Driver": "local",
            "Mode": "",
            "RW": true
        }・・・
```

#### 1.3. ホスト側のディレクトリをデータボリュームとしてマウント。
-vフラグでボリュームを作成できることに加え、コンテナに対してホスト側のディレクトリをマウントさせることが可能。
事前にホスト側で/src/webapp/testディレクトリを作成し、以下のコマンドを実行。ホストの/src/webappをコンテナの/opt/webappにマウントするようにする。

```
# docker run -i -t -P --name web2 -v /src/webapp:/opt/webapp training/webapp /bin/bash
root@cdedde19eb9a:/opt/webapp# ls /opt/webapp/
test
```

dfでは見えない。普通にmountしているわけではなさそう。

```
root@cdedde19eb9a:/opt/webapp# df -h
Filesystem                                                                                           Size  Used Avail Use% Mounted on
/dev/mapper/docker-253:1-406195091-cdedde19eb9a3cda8fbe922cc1ba76c1c1d00268eade2f668cc756ac2c34ef7d  9.8G  390M  8.9G   5% /
tmpfs                                                                                                 16G     0   16G   0% /dev
shm                                                                                                   64M     0   64M   0% /dev/shm
tmpfs                                                                                                 16G     0   16G   0% /sys/fs/cgroup
/dev/mapper/centos-root                                                                              118G   16G  102G  14% /etc/hosts
tmpfs                                                                                                 16G     0   16G   0% /proc/kcore
tmpfs                                                                                                 16G     0   16G   0% /proc/latency_stats
tmpfs                                                                                                 16G     0   16G   0% /proc/timer_stats
```

#### 1.4. ホストファイルをデータボリュームとしてマウント
-vフラグはディレクトリだけではなく、シングルファイルをマウントすることにも使用できる。

```
# docker run --rm -it -v /etc/hosts:/etc/hosts ubuntu /bin/bash
root@a8d8deb4005d:/# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.6 gpu02 gpu02
```

#2. データボリュームコンテナの作成とマウント
コンテナを跨いで永続的なデータを共有したい場合、データボリュームコンテナと呼ばれるコンテナを作成し、そこにデータをマウントするのが一番よいソリューションである。

データを共有するためのデータボリュームコンテナ(dbdata)を作成　※docker createはコンテナを作るまでで起動はしない。

```
# docker create -v /dbdata --name dbdata training/postgres /bin/true
c641ed5979bb32a83e7d8fdc11daa75fc59a65b5a0cb9bae7b19fc6c974d18bc
```
--volumes-from フラグを使って /dbdata ボリュームに他のコンテナをマウントする

```
# docker run -d --volumes-from dbdata --name db1 training/postgres
34dc616ff36bfa5d7b66a5e1fbc8c1bf1409a0df0513195cb97a1652a2b35891
```

```
# docker run -d --volumes-from dbdata --name db2 training/postgres
e078fc2b9447ad493262d3d8fdbfe40e1c8fa07363a9f308b6f5d1f3382ae50e
```

複数のコンテナで複数のデータボリュームを同時に使うには --volumes-from を複数回使用する。

```
# docker run -d --name db3 --volumes-from db1 training/postgres
6df2d9f628e05f0ec7bd234a0e4e6fe3e352ce75d373a4db9d333b9bb56d0699
```

```
# docker exec -i -t db1 /bin/bash
root@34dc616ff36b:/# df -h |grep dbdata
/dev/mapper/centos-root    118G   17G  101G  14% /dbdata
root@34dc616ff36b:/# touch /dbdata/aaa
```

```
# docker exec -i -t db2 ls /dbdata/
aaa ※db1で作ったファイルが共有されていることを確認
```

マウントしたボリューム、最初のdbdata 、 db1、 db2 コンテナなどを削除したい場合、ボリュームが１つでも参照されている間は削除することが出来ない。ディスクからボリュームを削除するためには、明確に”docker rm -v”を実行する必要がある。

データボリュームコンテナにより、コンテナ間におけるアップグレードや、効率的なデータボリュームの移行が可能となるメリットがある。

# 3. バックアップ、リストア、マイグレーション
データボリュームコンテナを使うもうひとつの有効な方法として、ボリュームをバックアップやリストア、マイグレーションのために使う事である。使うためには、新しいコンテナを作るときに—volumes-fromフラグを使ってボリュームをマウントする。

新しいコンテナを起動し、dbdataコンテナからボリュームをマウントする。それからコンテナにローカルホストのディレクトリ/backupとしてマウントする。最後にtarコマンドを使用してdbdataボリュームの内容をbackup.tarとしてバックアップする。（データボリュームコンテナのデータをローカルストレージにバックアップ）コマンドが完了し、コンテナを停止したとき、dabdataボリュームのバックアップは残ったままである。

```
# docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
tar: Removing leading `/' from member names   ※データボリュームコンテナの情報をローカルにバックアップ
/dbdata/
/dbdata/aaa
```

新しいデータボリュームコンテナ(dbdata2)を作成。次にコンテナを作成しデータボリュームコンテナとローカルホストのカレントディレクトリ（さっきバックアップのtarを置いたところ）をマウント。バックアップファイルを解凍し/dbdataにリストアを行う。

```
# docker run -v /dbdata --name dbdata2 ubuntu /bin/bash
# docker run --volumes-from dbdata2 -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar -C /dbdata
dbdata/
dbdata/aaa
```