nvidia-docker2を試してみる

nvidia-dockerが正式にリリースされたのは2017年1月。コンテナにGPUを簡単に利用できるのはその利点の一つ。もう一つはホストに複数のGPUを搭載した際に、特定数または単独なGPUをコンテナ内に利用可能となります。しかしこのplug-inとdocker daemonは別々に取り組む、使用上に少々制限されてる。
2017年の年末に近い11月、nvidia-docker2がついにリリースされました。
[説明](https://github.com/NVIDIA/nvidia-docker/wiki/About-version-2.0)によると、要点が三つがあると思う。
1. dockerにnvidia-dockerを組み込んた、別々のdaemonは必要ない。
2. 従来バージョンとの互換性。
3. イメージはCUDA無くとも、コンテナ内にGPUも利用できます。

とりあえず設置の流れをメモして、加えて気になる機能を試してみましょう。

##システム配置
- ubuntu 16.04
- dockerインストール済
- nvidiaドライバインストール済


## nvidia-docker2を導入
###レポジトリ追加
```bash
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
  sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
```
###nvidia-docker2をインストール
nvidia-docker2は現時点でまたすべてのdockerバージョンにサポートされていないため、nvidia-docker2をインストールする前に、まずdockerバージョンを確認して、必要であれば対応バージョンに更新する。

```console:dockerバージョン確認
ishouyou@emerald:~$ docker --version
Docker version 1.12.5, build 7392c3b
```

```console:サーポートバージョン確認
ishouyou@emerald:~$ sudo apt-cache madison nvidia-docker2 nvidia-container-runtime
...
nvidia-docker2 | 2.0.1+docker1.12.6-1 | https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64  Packages
...
nvidia-container-runtime | 1.1.0+docker1.12.6-1 | https://nvidia.github.io/nvidia-container-runtime/ubuntu16.04/amd64  Packages
...
```
```console:対応dockerバージョンに更新
ishouyou@emerald:~$ sudo apt-cache madison docker-engine
ishouyou@emerald:~$ sudo apt-get install docker-engine=1.12.6-0~ubuntu-xenial
ishouyou@emerald:~$ sudo pkill -SIGHUP dockerd
```
もしホストにnvidia-docker v1.0がインストールされていて、またはnvidia-docker daemonで追加されたコンテナがある場合、そのコンテナを一旦消去して、nvidai-docker 1.0をパージします。

```console:nvidai-dockerをパージする
ishouyou@emerald:~$ docker volume ls -q -f driver=nvidia-docker | xargs -r -I{} -n1 docker ps -q -a -f volume={} | xargs -r docker rm -f
ishouyou@emerald:~$ sudo apt-get purge nvidia-docker
```

```console:nvidia-docker2とnvidia-container-runtimeをインストールする
ishouyou@emerald:~$ sudo apt-get install -y nvidia-docker2=2.0.1+docker1.12.6-1 nvidia-container-runtime=1.1.0+docker1.12.6-1
ishouyou@emerald:~$ sudo pkill -SIGHUP dockerd
```
ここでnvidia-docker2のインストールは完了です。

###nvidia-docker2の使用方法
使い方は変わりますが、互換性はバッチリですから、v1.0に慣れた人に同じの使用方法も通じます。

```console:従来nvidia-dockerの使い例
NV_GPU='0' nvidia-docker run --rm nvidia/cuda nvidia-smi
```
nvidia-docker2は上記のコメンドを自動転換して、下記のようになります。

```console:nvidia-docker2の使い例
docker run --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=0 --rm nvidia/cuda:8.0-cudnn6-devel-ubuntu16.04 nvidia-smi
```

###CUDAなしのイメージでも使える
ホストにインストールされたCUDAバージョンをコンテナにアクセスことができます。

```console:GPU使用できるのコンテナ作成例
docker run --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=0 --rm busybox:latest nvidia-smi
```


## nvidia-docker2とrancherの組み合わせ
![rancher.jpg](https://qiita-image-store.s3.amazonaws.com/0/211063/018ff5a9-be54-ae75-0b40-38a85a2a6dfd.jpeg)

###docker daemonを設置
docker daemonデバッグモードで試す


```console:dockerデバッグモードを作動する
sudo systemctl stop docker
sudo dockerd -D --default-runtime=nvidia
```

```console:dockerd
...
DEBU[0004] attach: stdout: end
DEBU[0004] attach: stderr: end
DEBU[0004] Calling POST /v1.22/containers/91af6039e0ab33376fb04a16a5743f75957
66ff2e06a923f0d4454c954032328/wait
DEBU[0004] Calling GET /v1.22/containers/91af6039e0ab33376fb04a16a5743f759576
6ff2e06a923f0d4454c954032328/json
DEBU[0004] Calling DELETE /v1.22/containers/91af6039e0ab33376fb04a16a5743f759
5766ff2e06a923f0d4454c954032328?v=1
DEBU[0004] Calling GET /v1.22/containers/rancher-agent/json
DEBU[0006] Calling GET /v1.22/info
DEBU[0006] Calling GET /v1.22/version
DEBU[0006] Calling GET /v1.22/info
DEBU[0006] Calling GET /v1.22/containers/json?all=1&filters=%7B%22status%22%3
A%7B%22paused%22%3Atrue%2C%22running%22%3Atrue%7D%7D&limit=0
DEBU[0006] Calling GET /v1.22/events
DEBU[0007] Calling GET /v1.22/containers/json?all=1&limit=0
DEBU[0013] Calling GET /v1.22/containers/json?all=1&limit=0
DEBU[0013] Calling GET /v1.22/containers/a108a5f2c630df4ec6644d4eeae10834612c
15a6a2780b6c9cc7513955eee905/json
DEBU[0013] Calling GET /v1.22/containers/json?all=1&limit=0
DEBU[0013] Calling POST /v1.22/containers/a108a5f2c630df4ec6644d4eeae10834612
c15a6a2780b6c9cc7513955eee905/start
...
```
###コンテナを追加
Rancher Web UIから見ると、ホストの配置はほぼ丸見えです。（IPアドレスの部分は隠させていただきます。）
![rancher_host.png](https://qiita-image-store.s3.amazonaws.com/0/211063/552d9322-414b-75db-d073-35c85567771a.png)

```console:ホスト側で
ishouyou@ubuntu:~$ nvidia-smi
Thu Dec  7 18:54:30 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.66                 Driver Version: 384.66                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P4            Off  | 00000000:04:00.0 Off |                    0 |
| N/A   28C    P0    23W /  75W |      0MiB /  7606MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P4            Off  | 00000000:83:00.0 Off |                    0 |
| N/A   30C    P0    23W /  75W |      0MiB /  7606MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```
Web UIからコンテナを追加するのはこんな感じです。
![add_container.png](https://qiita-image-store.s3.amazonaws.com/0/211063/5314a005-4832-e5d3-0ec2-396ac55c47ce.png)

特に注意すべきのは、その変数です。NVIDIA_VISIBLE_DEVICESはGPUを設置するnvidia-docker2の変数です。
![add_container_2.png](https://qiita-image-store.s3.amazonaws.com/0/211063/5be5e698-f882-3850-7d4e-2fa9789c6819.png)
NVIDIA_VISIBLE_DEVICESの変数に、値の部分は0が書いてのはGPU 0を利用する。もし全部のGPUが使いたい時、allに記入します。
作成ボタンを押して、GPU利用可能なコンテナを作成することが始めます。
コンテナ作成完了の後、コンソールで確認。

```console:コンテナの中に入る
ishouyou@ubuntu:~$ docker exec -it r-hoge_gpu_0-7e8ff0a0 bash
root@c3a336340dad:/# nvidia-smi
Thu Dec  7 19:01:25 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.66                 Driver Version: 384.66                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P4            Off  | 00000000:04:00.0 Off |                    0 |
| N/A   28C    P0    23W /  75W |      0MiB /  7606MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```
dockerデバッグモードで試し終わりましたら、デバッグモードを終了し、docker daemon設定に書き込む。

###docker daemonに設置

```json:daemon.json
{
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "default-runtime": "nvidia"
}
```
```console:dockerdを再起動する
sudo pkill -SIGHUP dockerd
```