nVIDIA-docker2 を dockerから導入してみよう。


# 初めに

nVIDIA docker2を使って、機械学習の環境を作っている方も多いと思います。
今回はその手順をまとめたものを記事にしました。


ちなみに、これは前回書いたエントリの続き的な物になります。
　[AWS EC2のGPUが使えるubuntu16.04に、自力でCUDA 9.2/CuDNNを入れてみよう](https://qiita.com/maloney-san/items/fca3439a3f635428b82b)

前回は、cuda/cudnnを導入した環境まで構築しました。 次はdockerの環境を導入します。

環境は、大体以下。
　ubuntu: 16.04  (AWS上です)
　CUDA: 9.2
　cudnn: 7_7.5.0.56-1
 
# そもそも、なぜDockerを使うのか？

すでに多くの方が説明済みかと思いますので、ここでは多くは触れません。
大きくは以下のメリットがあるかと思います。

- コンテナ化すると、複製が容易かつ作った環境をどこにでも持っていくことができる
  - 気軽に複製可能なので、変更したり環境の管理ができる。
  - クラウドでもオンプレでも簡単に展開できる。チームに展開しやすい。
  
今回は、Docker を導入後、nVidia Dockerを導入して軽く確認するところまで説明します。


# Docker のセットアップ

これも同様。 基本的に公式の手順を見るほうが良いです。

https://docs.docker.com/install/linux/docker-ce/ubuntu/

古いバージョンのものが入っていないか確認をします。

```
$ dpkg -l | grep docker
$ dpkg -l | grep runc
$ dpkg -l | grep containerd
$
```

次に必要なパッケージとgpgキーの入手

```
$ sudo apt-get update
～略～
$ sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common 
～略～
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
～略～
```

リポジトリなどを追加し、docker本体をインストールします。

```
※バージョンを指定しない場合の手順です。

$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
```

なお、VLを指定したい場合は以下を実行するとよいでしょう。

```
※バージョンを指定する場合は↓のコマンドでバージョンの一覧を取得して、指定します。
$ apt-cache madison docker-ce 
 docker-ce | 5:18.09.3~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
 docker-ce | 5:18.09.2~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
 docker-ce | 5:18.09.1~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
 docker-ce | 5:18.09.0~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
 docker-ce | 18.06.3~ce~3-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
 docker-ce | 18.06.2~ce~3-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
 docker-ce | 18.06.1~ce~3-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
…
```

無事インストールできたことの確認をします。
hello-worldというコンテナイメージをPullしてきて、で、それを起動させるとよいかも。

```
$ sudo docker --version
Docker version 18.09.3, build 774a1f4
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

```

これで、dockerまでは完了です。

## nVIDIA-Docker 2 のセットアップ

では次にnvidia-docker2のセットアップになります。
ネット上の記事を見ると、nvidia-docker 1 の情報が散見されますので、
色んなページを見まくっている人は気を付けたほうが良いかもしれません。

nVidia dockerについても、基本的に公式手順を見ます。

https://github.com/NVIDIA/nvidia-docker

以降の手順は、公式手順を少しだけアレンジされているものです。
runtimeも同時セットアップをしています。


```
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
> sudo apt-key add -
OK
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \
>   sudo tee /etc/apt/sources.list.d/nvidia-docker.list
deb https://nvidia.github.io/libnvidia-container/ubuntu16.04/$(ARCH) /
deb https://nvidia.github.io/nvidia-container-runtime/ubuntu16.04/$(ARCH) /
deb https://nvidia.github.io/nvidia-docker/ubuntu16.04/$(ARCH) /
$ sudo apt update
```

利用中のdockerのVersionと一致している物を確認して、インストールします。
↑のほうで、$ sudo docker --version と実行していた結果を使います。

```
$ apt-cache madison nvidia-docker2 nvidia-container-runtime | grep <dockerのVersion>
nvidia-docker2 | 2.0.3+docker18.09.3-1 | https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64  Packages
nvidia-container-runtime | 2.0.0+docker18.09.3-1 | https://nvidia.github.io/nvidia-container-runtime/ubuntu16.04/amd64  Packages
$ 
$ sudo apt install -y nvidia-docker2=2.0.3+docker18.09.3-1 nvidia-container-runtime=2.0.0+docker18.09.3-1
```

インストールができたかどうか確認しましょう。 CLIの動作などで確認になるのかなと思います。

```
$ nvidia-container-cli info
NVRM version:   396.82
CUDA version:   9.2

Device Index:   0
Device Minor:   0
Model:          Tesla K80
Brand:          Tesla
GPU UUID:       GPU-68403f5f-27e8-1262-bdd8-f12bd502d1b2
Bus Location:   00000000:00:1e.0
Architecture:   3.7
ubuntu@ip-10-10-224-17:~$ 
ubuntu@ip-10-10-224-17:~$ 
ubuntu@ip-10-10-224-17:~$ nvidia-container-cli list
/dev/nvidiactl
～略～
/usr/lib32/nvidia-396/libGLESv1_CM_nvidia.so.396.82
/run/nvidia-persistenced/socket
```

docker deamon の condigをreloadします。

```
$ sudo pkill -SIGHUP dockerd
```

また、個人的なおすすめとして、
docker の操作を一般ユーザにも開放したほうがよいと思います。
以下は、sudo 不要で一般ユーザでも操作できるようにするための手順です。
これをやると、ubuntu ユーザでsudoなしでdockerが操作できます。

```
$ groups
ubuntu adm dialout cdrom floppy sudo audio dip video plugdev netdev
$ sudo adduser -a ubuntu docker
Adding user `ubuntu' to group `docker' ...
Adding user ubuntu to group docker
Done.
$ 
～再ログインなどする～
$ groups
ubuntu adm dialout cdrom floppy sudo audio dip video plugdev netdev lxd docker
$ 
```

ということで、 nvidia docker2 が正常に動くことを確認します。

使うコンテナのイメージは公式に提供済みのものがありますのでそれを指定。
cuda toolkitのnvidia-smiとcuda CLIの nvccの動作確認ができれば
コンテナからGPUが使える状態になっているのかなーと思います。

```
$ docker run --runtime=nvidia --rm nvidia/cuda:9.2-cudnn7-devel-ubuntu16.04 nvidia-smi
Fri Mar  8 12:37:33 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 396.82                 Driver Version: 396.82                    |
|-------------------------------+----------------------+----------------------+
| 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 K80           Off  | 00000000:00:1E.0 Off |                    0 |
| N/A   61C    P0    57W / 149W |      0MiB / 11441MiB |     99%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
$ docker run --runtime=nvidia --rm nvidia/cuda:9.2-cudnn7-devel-ubuntu16.04 /usr/local/cuda-9.2/bin/nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2018 NVIDIA Corporation
Built on Tue_Jun_12_23:07:04_CDT_2018
Cuda compilation tools, release 9.2, V9.2.148
```

これでnVidia Dockerの導入まで終わりです。
次は、導入したnvidia docker を使って、そこにフレームワークを導入するとか、サンプルを動かす例を書いていくかもしれません。たぶん