nvidia-docker2をUbuntuにインストールしてdocker-composeから実行する。

## この記事の概要

**Ubuntuにnvidia-docker2を入れてdocker-composeで実行するまでの手順の記録です。**

nvidia-docker2とは、Dockerコンテナ上からCUDAを使用するために必要なツールです。
コンテナ上ではなくホストコンピューターにインストールしてあげる必要があります。


### この記事の構成
* 手順の前半でdockerのインストールとnvidia-docker2のインストールを行います。
* 手順の後半ではdocker-composeのインストールを行います。

docker-composeを使わない人は、後半の手順は無視して大丈夫です。

### 環境
* OS: Ubuntu 16.04
* GPU: Tesla K80 × 2枚
* CPU: x86_64

ちなみにGCP上で確認しました。

### この記事で解説する手順
* dockerのインストール
* nvidia-docker2のインストール
* Dockerコンテナ上でのCUDA動作確認
* docker-composeのインストール

## 1. dockerインストール

まず**dokcer-ce**をインストールします。
docker-ceというのは、dockerの無償版(コミュニティエディション)の事です。

* aptリポジトリの追加

```bash
$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
```

* インストール

```bash
$ sudo apt-get install docker-ce=17.12.0~ce-0~ubuntu
```

※2018/02/27現在、nvidia-docker2がdocker-ce v17.12.0を求めてくるのでバージョンを指定してインストールしています。

* 動作確認
* 
dockerコンテナの中でhello worldして、ホストOSの標準出力に表示します。

```bash
$ sudo docker run hello-world

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

Hello from Docker!と表示されたら成功です。

## 2. CUDAのインストール

CUDAをインストールします。
debファイルが配布されていたのでそれを使います。

* debファイルのダウンロード

```bash
$ curl -O http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
```

* インストール

```bash
$ sudo dpkg -i cuda-repo-ubuntu1604_9.1.85-1_amd64.deb
$ sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get install cuda
```

* 設定

環境変数PATHおよびLD_LIBRARY_PATHにCUDAのディレクトリを通してあげる必要があります。
.bashrcなどの以下のコマンドを追記しよう。

```bash:~/.bashrc
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/local/cuda/lib:$LD_LIBRARY_PATH
```

```bash
$ vim ~/.bashrc  # bashrcをvimで開く。上記のexport文を追記する。
```

```bash
$ exit  # .bashrcを更新した後一度ログアウトする。再度ログインすると設定が反映される。
```

* 動作確認

nvccコマンドを使ってインストール出来たか確認します。

```
$ nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Nov__3_21:07:56_CDT_2017
Cuda compilation tools, release 9.1, V9.1.85
```

バージョンが表示されれば成功です。

## 3. nvidia-docker2のインストール

nvida-docker2をインストールします。

* aptリポジトリの設定

```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
```

* インストール

```bash
$ sudo apt-get install nvidia-docker2
```

* dockerデーモンの再起動

dockerデーモンを再起動することでnvidia-docker2が使えるようになります。

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

* 動作確認。

dockerコンテナ上でnvidia-smiを実行します。

```bash
$ sudo docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.30                 Driver Version: 390.30                    |
|-------------------------------+----------------------+----------------------+
| 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:04.0 Off |                    0 |
| N/A   58C    P0    74W / 149W |      0MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla K80           Off  | 00000000:00:05.0 Off |                    0 |
| N/A   60C    P0    79W / 149W |      0MiB / 11441MiB |    100%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

GPUの実行状況が出たら成功です。

* 動作確認2

nvccもコンテナ上で実行してみましょう。

```
$ sudo docker run --runtime=nvidia --rm nvidia/cuda nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Sep__1_21:08:03_CDT_2017
Cuda compilation tools, release 9.0, V9.0.176
```

バージョンが出たら成功です。

## 4. docker-composeインストール

**docker-compose**をインストールします。

docker-composeとは複数のdokcerコンテナを管理しやすくするためのツールです。
無くてもnvidia-docker2は使えます。

注意点が1つあります。
**この後の手順はdokcer-compose 1.19.0以降を想定しています。**
これ以前のバージョンだとdokcer-compose.yamlの書き方が変わるので注意しましょう。

インストール手順

* 実行ファイルのダウンロード

```bash
$ sudo curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
```

* 実行権限の付与

```bash
$ sudo chmod +x /usr/local/bin/docker-compose
```

* 動作確認

```bash
$ sudo docker-compose --version
docker-compose version 1.19.0, build 9e633ef
```

docker-composeのバージョンが表示されれば成功です。

* nvidia-docker2をdocker-compose上で実行

nvidia-docker2をdocker-composeから実行してみましょう。
docker-compose.yamlはこのように書きました。

* ポイントは2つ
    * `runtime`で`nvidia`を指定する。
    * `version`で`'2.3'`を指定する。

version 2.3を指定するのは、`runtime`に対応したのが2.3だからです。
参考: https://github.com/docker/compose/releases/tag/1.19.0

```yaml:docker-compose.yaml
version: '2.3'
services:
  nvidia:
    image: nvidia/cuda
    runtime: nvidia
    command: nvidia-smi
```

* 実行


```bash
$ sudo docker-compose up
Starting sabaku2017_nvidia_1 ... done
Attaching to sabaku2017_nvidia_1
nvidia_1  | Tue Feb 27 10:15:14 2018       
nvidia_1  | +-----------------------------------------------------------------------------+
nvidia_1  | | NVIDIA-SMI 390.30                 Driver Version: 390.30                    |
nvidia_1  | |-------------------------------+----------------------+----------------------+
nvidia_1  | | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
nvidia_1  | | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
nvidia_1  | |===============================+======================+======================|
nvidia_1  | |   0  Tesla K80           Off  | 00000000:00:04.0 Off |                    0 |
nvidia_1  | | N/A   59C    P0    77W / 149W |      0MiB / 11441MiB |    100%      Default |
nvidia_1  | +-------------------------------+----------------------+----------------------+
nvidia_1  | |   1  Tesla K80           Off  | 00000000:00:05.0 Off |                    0 |
nvidia_1  | | N/A   61C    P0    84W / 149W |      0MiB / 11441MiB |      0%      Default |
nvidia_1  | +-------------------------------+----------------------+----------------------+
nvidia_1  |                                                                                
nvidia_1  | +-----------------------------------------------------------------------------+
nvidia_1  | | Processes:                                                       GPU Memory |
nvidia_1  | |  GPU       PID   Type   Process name                             Usage      |
nvidia_1  | |=============================================================================|
nvidia_1  | |  No running processes found                                                 |
nvidia_1  | +-----------------------------------------------------------------------------+
sabaku2017_nvidia_1 exited with code 0
```

nvidia-docker2をdocker-compse上で実行してCUDAを使うことが出来ました。

## 参照元
* dockerインストール http://docs.docker.jp/linux/step_one.html
* docker-compose インストール https://docs.docker.com/compose/install/#install-compose
* CUDA インストール https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1604&target_type=debnetwork
* nvidia-docker2 インストール時のリポジトリ追加 https://nvidia.github.io/nvidia-docker/