DockerでDeep Learningなどの環境をドカドカ構築

#はじめに

最近はみんなDeep Learningに興味津々だね！
えっ？環境構築が難しくて手が出せない？

確かにGPUが絡んだ途端に周りのライブラリの整備とか無限に面倒だし，右も左もわからない人には環境構築がまず敷居が高くて手が出せないし，
そもそもネットに落ちてるサンプルとかはフレームワークそのものが違ったり，フレームワークのバージョンが違うのがいくつもあって，フレームワークの切り替えが大変で使いこなすのが難しいよね...

でも大丈夫！今時のDeep Learningフレームワークは公式でDocker Imageを配っていたり，GitHubでDockerfileを配っているのがほとんどだから，それをちょっと改変するだけで，あっという間に環境構築が出来るんだ！

最初の設定は，慣れてない人にはちょっと手こずるかもしれないけど，一度設定すればあらゆる環境をすぐに切り替えて動かすことが出来るよ！

#必要な物（物理）
 - Nvidia GPUが入ったLinuxマシン
 - ストレージ(仮想環境をドカドカ立てるのであれば，自由に使える容量が100GBは欲しい)

#環境構築手順
以下Ubuntuを前提にして話を進めます

## GPUドライバーインストール

[公式ページ](https://www.nvidia.co.jp/object/unix-jp.html)からダウンロード出来るので，それに実行権限を付けて実行しましょう．
通常以下のコマンドで大丈夫なはずです．

```bash
chmod +x (ダウンロードしたファイル)
sudo ./(ダウンロードしたファイル)
```
です．
インストール中は色々聞かれますが，適宜対処してください．

## dockerインストール

aptでインストール...と言いたいところですが，aptで通常インストール出来る奴はバージョンが古かったりしてあまり推奨されてないので，[公式](https://docs.docker.com/install/linux/docker-ce/ubuntu/)に従ってインストールしましょう．
なお，デフォルトではdockerはsudoを付けないと動作しませんが，それが嫌って人は，自分のアカウントをdockerが所属するグループに紐づけましょう．

(参考)
[Dockerコマンドをsudoなしで実行する方法](https://qiita.com/DQNEO/items/da5df074c48b012152ee)

## nvidia-dockerインストール

[公式GitHub](https://github.com/NVIDIA/nvidia-docker)のQuickstartの所を実行してください．
なお，上記の方法でdockerをインストールした場合は最初から最新のdockerが入ってるはずなので，二番目のリポジトリを追加するところから始めて大丈夫です．

## Docker Imageの用意

### 公式が配布するDocker Imageを入手する
メジャーなフレームワークだったら，Docker Imageが配布されている場合があるので，DockerfileをBuildする手間が省けます．
ただし環境をカスタマイズしたいなら，後述のようにDockerfileからビルドした方が良いです．
#### Tensorflowの例
 1. [TensorflowのDockerHub](https://hub.docker.com/r/tensorflow/tensorflow/) にアクセスして，Tagsから欲しいバージョンのimageを見つけます．
 2. 次のコマンドを入力してdocker imageを落としてきます

```bash
docker pull tensorflow/(欲しいTagの名前)
``` 

### (Docker Imageが無い場合)公式のGitHubのページにいってcloneする
だいたいのメジャーなDeepLearningフレームワークはGitHubのページがあるので，それをcloneしましょう
#### Pytorchの例
 - [PytorchのGitHub](https://github.com/pytorch/pytorch)にアクセスして，git cloneします．
 - docker/pytorchディレクトリに移って，Dockerfileを確認します.するとこのような中身があるはずです．

  ```公式Dockerfile
FROM nvidia/cuda:10.0-cudnn7-devel-ubuntu16.04
ARG PYTHON_VERSION=3.6
RUN apt-get update && apt-get install -y --no-install-recommends \
         build-essential \
         cmake \
         git \
         curl \
         vim \
         ca-certificates \
         libjpeg-dev \
         libpng-dev &&\
     rm -rf /var/lib/apt/lists/*


RUN curl -o ~/miniconda.sh -O  https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh  && \
     chmod +x ~/miniconda.sh && \
     ~/miniconda.sh -b -p /opt/conda && \
     rm ~/miniconda.sh && \
     /opt/conda/bin/conda install -y python=$PYTHON_VERSION numpy pyyaml scipy ipython mkl mkl-include cython typing && \
     /opt/conda/bin/conda install -y -c pytorch magma-cuda100 && \
     /opt/conda/bin/conda clean -ya
ENV PATH /opt/conda/bin:$PATH
RUN pip install ninja
# This must be done before pip so that requirements.txt is available
WORKDIR /opt/pytorch
COPY . .

RUN git submodule update --init
RUN TORCH_CUDA_ARCH_LIST="3.5 5.2 6.0 6.1 7.0+PTX" TORCH_NVCC_FLAGS="-Xfatbin -compress-all" \
    CMAKE_PREFIX_PATH="$(dirname $(which conda))/../" \
    pip install -v .

RUN git clone https://github.com/pytorch/vision.git && cd vision && pip install -v .

WORKDIR /workspace
RUN chmod -R a+w /workspace
  ```
  中を見れば大体何やってるかわかると思いますが，ここではapt-getで最小限の環境をそろえて，ビルド環境を整えて，condaをインストールしてからそこにpytorchをビルドしてインストールしてます．

  あとは自分が欲しいものに応じてDockerfileを編集してください．

 - Dockerfileを以下のコマンドでbuildします．
 
 ```bash
 
 docker build -t (tagの名前) .
 ```
Dockerfileがあるディレクトリでビルドすることに気を付けてください．
大抵のDeepLearningフレームワークでは，Dockerfileが存在するディレクトリでビルドすることが想定されています（それ以外でビルドしたらエラーが起こった）

## docker-compose.ymlの記述

ビルド出来たらいよいよコンテナを起動して使う...前にdocker-composeでコンテナを簡単に扱いやすくしましょう．
以下がtensorflowのdocker-composeの例です．

```docker-compose.yml

version: '2.3'
services:
    tensorflow:
        container_name: tensorflow_1
        image: tensorflow/tensorflow:latest-gpu-py3-jupyter
        volumes:
            - /path/to/data:/mnt
        runtime: nvidia
        tty: true
        command: /bin/bash
        ports:
            - 8889:8889
```

詳しい解説は他の物に譲りますが，ここで設定しているのは以下のようになります．

- version: docker-composeのバージョン．古いとnvidia-dockerが動かないので，2.3を指定しています．
- services:tensorflow: サービスの名称を決めます．ここ被ると他のdocker-composeで操作されるので被らないようにしましょう
- container_name:コンテナ名を決める．docker psなどで確認したりする際に重要
- image:DockerHubから取ってきたりビルドしたりしたimageファイルを指定
- volumes:Dockerホストとのデータをやり取りする場所を指定．大体の環境では/mntがあるので，自分はいつも，Dockerホストの共有したいフォルダを/mntにマウントしてます
- runtime: nvidia-dockerを動かすために必要なおまじない
- tty: true :ここfalseだと，dockerが起動即終了するので，立ち上げてすぐプログラムを走らせて終了，みたいな使い方じゃなければ，trueにして，あとからexecコマンドで動作させましょう．
- command: 起動した際に走らせるコマンドです．
- ports:Dockerホストとつなげたいポートです．

## 起動&実行
以上までで環境構築及びdocker-compose.ymlの記述が終わったら，ymlファイルがあるところに移動して次のコマンドでコンテナを起動してください．

```bash
docker-compose up -d
```

するとコンテナが起動するので，psコマンドで以下のように出るはずです．

```bash
docker ps

CONTAINER ID        IMAGE                                          COMMAND                CREATED              STATUS              PORTS                              NAMES
89a5fb55012c        tensorflow/tensorflow:latest-gpu-py3-jupyter   "/bin/bash"            3 days ago          Up 3 days           8888/tcp, 0.0.0.0:8889->8889/tcp   tensorflow_1
```

このコンテナに対してtensowflowを行う場合は，以下のexecコマンドでコンテナの中でbashを起動します

```bash
docker exec -it 89a5 /bin/bash
```

ここでは，IDが89a5fb55012cなので，-itの後に89a5とこのIDを特定できる文字列を渡せばそのコンテナの中に入れます．
あとは，中にtensowflowの環境が用意されているので，思いっきりDeepLearningをするだけです！

#DockerHubにimageがある著名なDeepLearningフレームワーク例

著名なDeepLearningフレームワークにはDockerHubにimageが転がってきて，しかも大体最新のバージョンのimageが直ぐに配布されるので，その中から使いたいものを使いましょう

 - [Tensorflow](https://hub.docker.com/u/tensorflow)
 - [Pytorch](https://hub.docker.com/r/pytorch/pytorch)
 - [Chainer](https://hub.docker.com/r/chainer/chainer)

#GitHubにDockerfileがあるフレームワーク（DeepLearningとは限らない）例
DockerHubに公式のものが無い場合は，GitHubに転がってるDockerfileを使うのがオススメです．
他人が作ったImageもあることにはありますが，公式で配布されているものを使った方が確実だったり，自分好みの環境を整えたりと考えると自前でbuildした方が良い気がします
 -[WebDNN](https://github.com/mil-tokyo/webdnn)
  ブラウザ上でDeepLearningが出来るようになるフレームワーク．使うためにはサーバーの設定とかややこしい設定がいくつかありますが，Dockerでなら一発で出来ます
 -[LightGBM](https://github.com/Microsoft/LightGBM)
  DeepLearningではないですが，Kaggleなどのコンペで用いられる決定木ベースのアンサンブル学習の実装です．GPU周りの設定などもこのDockerfileを使えば一発でわかります．


#終わりに
いかがでしたでしょうか．機械学習関係は時代が進むにつれてどんどん新しいものが出てくるため，一つの環境に色々と混在させているとやっかいなことになりがちですが，Dockerを使えば様々な環境を同時に便利に扱うことが出来ます．Dockerはもはや機械学習関係のことを行うのに必須な環境と言ってよいでしょう．みなさんの健闘をお祈りします．