Ubuntu18.04にDocker + nvidia-docker + Jupyter notebook + TensorFlowを導入してディープラーニング開発環境を構築する。

##当方の環境
OS: Ubuntu 18.04.3 LTS
GPU: Geforce RTX2060

##nvidiaドライバーをインストール
```
$ sudo apt update
$ ubuntu-drivers devices
```
推奨ドライバーを確認。

```
== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v000010DEd00001F08sv00001043sd000086AEbc03sc00i00
vendor   : NVIDIA Corporation
driver   : nvidia-driver-430 - distro non-free
driver   : nvidia-driver-435 - distro non-free recommended
driver   : xserver-xorg-video-nouveau - distro free builtin

```

当方は430を選びました。

```
$ sudo apt install nvidia-driver-430
$ reboot
```
再起動後に、ちゃんとインストールできたか確認。

```
$ nvidia-smi
Wed Jan 29 11:07:50 2020       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 430.50       Driver Version: 430.50       CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce RTX 2060    Off  | 00000000:01:00.0  On |                  N/A |
|  0%   52C    P8    20W / 170W |    425MiB /  5926MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1424      G   /usr/lib/xorg/Xorg                            26MiB |
|    0      1719      G   /usr/bin/gnome-shell                          51MiB |
|    0      1897      G   /usr/lib/xorg/Xorg                           164MiB |
|    0      2040      G   /usr/bin/gnome-shell                         133MiB |
|    0     14972      G   ...equest-channel-token=237419310588213813    47MiB |
+-----------------------------------------------------------------------------+
```

##Dockerをインストール
こちらを参考にしました。
https://docs.docker.com/install/linux/docker-ce/ubuntu/

```
$ sudo apt-get update
$ sudo apt-get 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 -
$ sudo apt-key fingerprint 0EBFCD88
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```

動作を確認。下記のように出ればOKです。

```
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
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/


```
sudoなしでDockerコマンドを操作するには、グループ作成とユーザー登録が必要です。

こちらの方の記事を参考にさせていただきました。
https://qiita.com/DQNEO/items/da5df074c48b012152ee
##nvidia-docker2をインストール
こちらを参考にしました。
https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)#prerequisites

```
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
   sudo apt-key add -
$ 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
$ sudo apt-get update
```

```
$ sudo apt-get install nvidia-docker2
$ sudo pkill -SIGHUP dockerd
```
```
$ nvidia-docker version
NVIDIA Docker: 2.2.2
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

```
きちんとバージョンが表示されればOKです。

##開発環境構築
こちらの方の記事を参考にさせていただきました。
https://qiita.com/hrappuccino/items/fe76e2ed014c16171e47

ただ当方の環境ではjupyter notebookの起動はできても、ファイルの新規作成等が出来ない状態だった為、
ランタイム特権を有効にしてみたら行けました。
https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

```
$ docker run --gpus all --privileged -it -p 8888:8888 -v ~/workspace:/tf tensorflow/tensorflow:latest-gpu-py3-jupyter
```
以上です。
もともとCUDAやcuDNNを直接インストールしていたのですが、トラブルが非常に多かった為、
Dockerの勉強がてら構築してみました。
改良、変更点等出ましたら追記します。
 
###追記 
keras CNNでネットワークを書いて学習を試みた際に、エラーが出てしまい調べてみたところ、
どうやらRTXシリーズ特有のトラブルがあるようです。
参考 : https://qiita.com/hirotow/items/6233266b5fe970203ec5

こちらを実行したら解決しました。

```
from tensorflow.compat.v1.keras import backend as K

tf.compat.v1.disable_eager_execution()
config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
K.set_session(tf.compat.v1.Session(config=config))
```
TensorFlow2.xの場合は、1.xへの置き換えが必要になるみたいです。

また、本記事ではnvidia-docker2を導入していますが、radiolさんのご指摘の通り、
nvidia-docker2は非推奨となっている為、nvidia-container-toolkitを導入するほうが
ベターかもしれません。