Docker調査 ~ ディスク編

今日は、Dockerのディスク管理について調べてみようと思います。

#参考ページ
中井さんのこのページが参考になります。
* [RHEL7におけるDockerのディスクイメージ管理方式](http://enakai00.hatenablog.com/entry/20140420/1397981156)
* [第68回　Dockerストレージドライバーの性能比較 (中井悦司) ](http://www.school.ctc-g.co.jp/columns/nakai/nakai68.html)
* [Fedora22のDockerでoverlayfsドライバーを利用する手順](http://enakai00.hatenablog.com/entry/2015/06/28/204932)
このあたりの情報をもとにDockerについて整理していきたいと思います。

#Dockerのディスク管理
中井さんのページに記載されている通り、DockerではDevice MapperによるThin-Provisioning機能を使っています。
Device MapperによるThin-Provisioning機能は、RedHatがDockerをubuntu以外のLinuxでも利用できるように、Linuxカーネルで動作できるように追加した機能です。たいへんありがたいですね。

##■Dockerのインストール時のディスクイメージ
Dockerをインストールしていないときはこのような状態です。

```
# df -h
ファイルシス            サイズ  使用  残り 使用% マウント位置
/dev/mapper/centos-root    18G 1001M   17G    6% /
devtmpfs                  905M     0  905M    0% /dev
tmpfs                     914M     0  914M    0% /dev/shm
tmpfs                     914M  8.5M  905M    1% /run
tmpfs                     914M     0  914M    0% /sys/fs/cgroup
/dev/sda1                 497M  162M  336M   33% /boot
# lsblk 
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   20G  0 disk 
├─sda1            8:1    0  500M  0 part /boot
└─sda2            8:2    0 19.5G  0 part 
  ├─centos-root 253:0    0 17.5G  0 lvm  /
  └─centos-swap 253:1    0    2G  0 lvm  [SWAP]
sr0              11:0    1 1024M  0 rom  
```

Dockerを起動すると、このようなプロセスが起動していますね。フォーマット処理が行われています。

```
root      19324  19297  0 09:21 ?        00:00:00 mkfs.ext4 -E nodiscard,lazy_itable_init=0,lazy_journal_init=0 /dev/mapper/docker-253:0-20253-base
```

ディスクはこのように変わり、ループバックデバイスが出ていることがわかります。

```
# df -h
ファイルシス            サイズ  使用  残り 使用% マウント位置
/dev/mapper/centos-root    18G  1.3G   17G    8% /
devtmpfs                  905M     0  905M    0% /dev
tmpfs                     914M     0  914M    0% /dev/shm
tmpfs                     914M  8.6M  905M    1% /run
tmpfs                     914M     0  914M    0% /sys/fs/cgroup
/dev/sda1                 497M  162M  336M   33% /boot
[root@DockerDirect ~]# lsblk 
NAME                         MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                            8:0    0   20G  0 disk 
├─sda1                         8:1    0  500M  0 part /boot
└─sda2                         8:2    0 19.5G  0 part 
  ├─centos-root              253:0    0 17.5G  0 lvm  /
  └─centos-swap              253:1    0    2G  0 lvm  [SWAP]
sr0                           11:0    1 1024M  0 rom  
loop0                          7:0    0  100G  0 loop 
└─docker-253:0-20253-pool    253:2    0  100G  0 dm   
  └─docker-253:0-20253-base  253:3    0   10G  0 dm   
loop1                          7:1    0    2G  0 loop 
└─docker-253:0-20253-pool    253:2    0  100G  0 dm   
  └─docker-253:0-20253-base  253:3    0   10G  0 dm   
```

loop0とloop1が追加されているのがわかります。
losetコマンドさらに確認すると、

```
# losetup 
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         1  0 /var/lib/docker/devicemapper/devicemapper/data
/dev/loop1         0      0         1  0 /var/lib/docker/devicemapper/devicemapper/metadata
```

つまり作成されたループバックデバイス/dev/loop0や/dev/loop1は、/var/lib/docker/devicemapper/devicemapperに紐づいていることがわかります。このディレクトリの中身はこのようなファイルです。

```
# ls -lh /var/lib/docker/devicemapper/devicemapper/
合計 293M
-rw-------. 1 root root 100G  7月 25 08:52 data
-rw-------. 1 root root 2.0G  7月 25 08:54 metadata

# qemu-img info data
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 292M

# qemu-img info metadata
image: metadata
file format: raw
virtual size: 2.0G (2147483648 bytes)
disk size: 740K
```

dataファイルもmetadataファイルもraw(スパース)ファイルになっていますね。

##■イメージを取得すると？
まずは、イメージを取得してみましょう

```
# docker pull centos 
latest: Pulling from docker.io/centos
f1b10cd84249: Pull complete 
c852f6d61e65: Pull complete
7322fbe74aa5: Already exists 
docker.io/centos:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:57554136c655abb33ecb7bb790b1db0279668d3763c3b81f31bc6c4e60e4a1f3
Status: Downloaded newer image for docker.io/centos:latest

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/centos    latest              7322fbe74aa5        5 weeks ago         172.2 MB
```

Centos:latestをダウンロードしましたが、さぁどうなったでしょうか。

```
# qemu-img  info data
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 484M

# qemu-img  info metadata 
image: metadata
file format: raw
virtual size: 2.0G (2147483648 bytes)
disk size: 904K
```

292Mから484Mに増えていることが確認できます。
192M増えていますから、ほぼイメージ分(172.2MB)くらいが増えたことになりますね。
取得したイメージも/var/lib/docker/devicemapper/devicemapper/dataファイル内に保存されています。

##■コンテナを起動すると？
では、Dockerコンテナを1個起動してみましょう

```
# docker run -it --name test00 centos /bin/bash                                                                  
Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
[root@46bed6620c0b /]# 
# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
46bed6620c0b        centos:latest       "/bin/bash"         About a minute ago   Up About a minute                       test00  
```

Ctrl+PQで抜けれます。exitはしないように。。。

```
# qemu-img  info data
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 485M

# qemu-img  info metadata
image: metadata
file format: raw
virtual size: 2.0G (2147483648 bytes)
disk size: 956K
```

dataのディスクサイズは、484Mから485Mとほとんど増えていないことがわかります。
コンテナとして、/bin/bashを動かすのに追加のディスクは必要ないということで、
かなりディスクスペースが節約されているようです。

では、このとき、loopデバイスはどうなっているのでしょうか。

```
# lsblk 
NAME                                                                                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
...
loop0                                                                                     7:0    0  100G  0 loop 
└─docker-253:0-20253-pool                                                               253:2    0  100G  0 dm   
  ├─docker-253:0-20253-base                                                             253:3    0   10G  0 dm   
  └─docker-253:0-20253-46bed6620c0b12328d9cd95110dab4a360c5a31875837184e36ef585b750d8e9 253:4    0   10G  0 dm   
loop1                                                                                     7:1    0    2G  0 loop 
└─docker-253:0-20253-pool                                                               253:2    0  100G  0 dm   
  ├─docker-253:0-20253-base                                                             253:3    0   10G  0 dm   
  └─docker-253:0-20253-46bed6620c0b12328d9cd95110dab4a360c5a31875837184e36ef585b750d8e9 253:4    0   10G  0 dm   
```

docker-253:0-20253-46bed6620c0b12328d9cd95110dab4a360c5a31875837184e36ef585b750d8e9が作成されていますね。

コンテナ内部を見てみるとわかりますが、作成されたディスクがマウントされていることがわかります。

```
# df -h
Filesystem                                                                                       Size  Used Avail Use% Mounted on
/dev/mapper/docker-253:0-20253-46bed6620c0b12328d9cd95110dab4a360c5a31875837184e36ef585b750d8e9  9.8G  219M  9.0G   3% /
tmpfs                                                                                            914M     0  914M   0% /dev
shm                                                                                               64M     0   64M   0% /dev/shm
tmpfs                                                                                            914M     0  914M   0% /run/secrets
/dev/mapper/centos-root                                                                           18G  1.5G   16G   9% /etc/hosts
tmpfs                                                                                            914M     0  914M   0% /proc/kcore
tmpfs                                                                                            914M     0  914M   0% /proc/timer_stats
```

では、コンテナを終了してみます。

```
# lsblk
NAME                        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
...
loop0                         7:0    0  100G  0 loop 
└─docker-253:0-20253-pool   253:2    0  100G  0 dm   
  └─docker-253:0-20253-base 253:3    0   10G  0 dm   
loop1                         7:1    0    2G  0 loop 
└─docker-253:0-20253-pool   253:2    0  100G  0 dm   
  └─docker-253:0-20253-base 253:3    0   10G  0 dm  
```

ループバックデバイスがなくなりました。
docker rm  test00を実行してコンテナを削除しておきます。


#ディスクの使用量
ディスクの使用量の調査をするために、もう少しわかりやすい試験をします。
Dockerコンテナを起動し、100M程度のデータを書き込みます。

```
# docker run -it --name test01 centos /bin/dd if=/dev/zero of=zero.file count=102400 bs=1024                   
Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.
                                                 102400+0 records in
102400+0 records out
104857600 bytes (105 MB) copied, 0.214952 s, 488 MB/s
```

そうするとディスクはこのようになります。

```
# losetup
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         1  0 /var/lib/docker/devicemapper/devicemapper/data
/dev/loop1         0      0         1  0 /var/lib/docker/devicemapper/devicemapper/metadata

# lsblk 
NAME                        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
...
loop0                         7:0    0  100G  0 loop 
└─docker-253:0-20253-pool   253:2    0  100G  0 dm   
  └─docker-253:0-20253-base 253:3    0   10G  0 dm   
loop1                         7:1    0    2G  0 loop 
└─docker-253:0-20253-pool   253:2    0  100G  0 dm   
  └─docker-253:0-20253-base 253:3    0   10G  0 dm   

# qemu-img  info data
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 585M

# qemu-img  info metadata                                                                                        
image: metadata
file format: raw
virtual size: 2.0G (2147483648 bytes)
disk size: 1.1M

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                     PORTS               NAMES
75347df847b3        centos:latest       "/bin/dd if=/dev/zer   3 minutes ago       Exited (0) 3 minutes ago                       test01  
```

Dockerではイメージを起動すると、ディスクが増えています。
dataは484Mから585Mに100Mくらい増えています。書き込んだ分だけ増える。
当然の結果です。

#ディスクのメタ情報
このとき、ディスクに書き込んだ情報は、/var/lib/docker/devicemapper/metadata以下に保存されているようです。

```
# find ./ -type f -print -exec /bin/bash -c 'cat {} | python -mjson.tool' \;
./transaction-metadata
{
    "device_hash": "75347df847b334b01ee5d01dd7b5a1a0ad5a0127738df9de28325fd6a1ce05c6",
    "device_id": 8,
    "open_transaction_id": 10
}
./base
{
    "device_id": 1,
    "initialized": true,
    "size": 10737418240,
    "transaction_id": 1
}
./f1b10cd842498c23d206ee0cbeaa9de8d2ae09ff3c7af2723a9e337a6965d639
{
    "device_id": 2,
    "initialized": false,
    "size": 10737418240,
    "transaction_id": 2
}
...(略)
./7322fbe74aa5632b33a400959867c8ac4290e9c5112877a7754be70cfe5d66e9
{
    "device_id": 4,
    "initialized": false,
    "size": 10737418240,
    "transaction_id": 4
}
./75347df847b334b01ee5d01dd7b5a1a0ad5a0127738df9de28325fd6a1ce05c6-init
{
    "device_id": 7,
    "initialized": false,
    "size": 10737418240,
    "transaction_id": 9
}
...(略)
```

#削除後のディスク使用量は？
##■コンテナのディスク削除
コンテナを削除してみます。きれいに作成する前のサイズに戻っていることがわかります。

```
# qemu-img  info data                                                                                  
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 585M

# docker rm test01
test01

# qemu-img info data                                                                                            
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 484M

```

##■イメージの削除
イメージを削除してみます。きれいにダウンロードする前のサイズに戻っていることがわかります。


```
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
docker.io/centos    latest              7322fbe74aa5        5 weeks ago         172.2 MB

# docker rm 7322fbe74aa5                                                                                         
Error response from daemon: no such id: 7322fbe74aa5
FATA[0000] Error: failed to remove one or more containers 

# docker rmi 7322fbe74aa5
Untagged: docker.io/centos:latest
Deleted: 7322fbe74aa5632b33a400959867c8ac4290e9c5112877a7754be70cfe5d66e9
Deleted: c852f6d61e65cddf1e8af1f6cd7db78543bfb83cdcd36845541cf6d9dfef20a0
Deleted: f1b10cd842498c23d206ee0cbeaa9de8d2ae09ff3c7af2723a9e337a6965d639

# qemu-img  info data
image: data
file format: raw
virtual size: 100G (107374182400 bytes)
disk size: 292M
```