たった2つのライブラリで、docker-compose内のコンテナでGPUを走らせ、最短の労力で開発を進める方法(2020年2月2日確認)


#  docker-composeを使う理由 
docker-composeはみなさん使ってますか? 

docker-composeはdocker runの際のoptionを全てyamlファイルで記述することができ、再現性を高めることができます。しかし、docker-compose内で```nvidia-smi```を走らせる、GPUを使うには一手間いるので今回は紹介したいと思います。 

僕は**optuna**で**Hyperparameter Tuning**するときに、探索結果を保存するmysqlのコンテナを立ち上げる必要があり、今回調査しました。 

![Haderz_ThumbNail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255540/b2473780-de2c-05c5-8634-fbe081de243c.png)
単純に、container内でgpuを走らせる場合は docker run に --gpus というオプションがあって、すぐに走らせられます。
[hotoさんの記事](https://qiita.com/hoto17296/items/be34849412e7ae9db6ff)や[mahoroiさんの記事](https://blog.mahoroi.com/posts/2019/12/docker-gpus-nvidia)が分かりやすかったです。
19.03以降のdockerに実装されたオプションのようで、詳しくは[NTT Labのこちらの記事](https://medium.com/nttlabs/docker-1903-5155754ff8ac)から

しかし、docker-compose内でGPUを走らせるには、
いろいろ詰まりどころがあったので、つまったところを詳しく解説します:raised_hand:
[@hgojさんの記事](http://bit.ly/2tmme8f)と[@verb55さんの記事](http://bit.ly/2tjS855)を参考にさせていただきました。

#  この記事の要約
- nvidia周りのdockerは開発サイクルが早く、情報が乱立している。
- docker, docker-composeだけでなく、nvidia-docker, nvidia-container-runtimeも入れましょう
- stackoverflow や githubのissueは偉大



# 概要
1. [nvidia-dockerのインストール](http://bit.ly/37Rwhkr)
2. [nvidia-container-runtimeのインストール](http://bit.ly/2GRoTcV)
3. [nvidia-docker2のインストールと/etc/docker/daemon.jsonの設定](http://bit.ly/2v04csD)
4. [docker-compose.ymlとDockerfileの準備](http://bit.ly/2uR18iB)
5. [出くわしたエラー:eyes:](http://bit.ly/36Tuji9)

##　環境
```
OS           : 18.04.3 LTS (Bionic Beaver)
docker       : 19.03.5
Cuda         : 10.1
nvidia-driver: nvidia-driver-440
cuDNN        : 7.6.5.32-1+cuda10.1
GCC          : 8.3.0 
```

## 前提条件
NvidiaDriver等、docker-compose, dockerが入っていて、GPUを回せる状態にあること　

## 1. nvidia-dockerのインストール
[Githubの公式サイト](https://github.com/NVIDIA/nvidia-docker)通りにします。

```Shell
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
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 -y nvidia-container-toolkit
sudo systemctl restart docker
```
`unknown flag: --gpus`のエラーはdockerのアップデートで解決

## 2. nvidia-container-runtimeのインストール
こちらも[Githubの公式サイト](https://github.com/NVIDIA/nvidia-container-runtime)から

```
curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | \
  sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list
sudo apt-get update
sudo apt-get install nvidia-container-runtime
```

## 3. nvidia-docker2のインストールと/etc/docker/daemon.jsonの設定
ここが一番詰まったところです。この[コメント](https://github.com/NVIDIA/nvidia-docker/issues/1073#issuecomment-532104398)と[コメント](https://github.com/NVIDIA/nvidia-docker/issues/1073#issuecomment-533257434)で解決しました。

```
sudo apt-get install nvidia-docker2 
sudo systemctl daemon-reload
sudo systemctl restart docker
```

```
{
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}
```
nvidia-docker2のインストールでファイルに自動的に書き込まれるため、こちらの設定はいらなくなりました。
一行目の`"default-runtime": "nvidia",`の追加だけ、必要です。[stackoverflowの記事](https://stackoverflow.com/questions/47465696/how-do-i-specify-nvidia-runtime-from-docker-compose-yml)

```
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}
```
## 4. docker-compose.ymlとDockerfileの準備

```Dockerfile
FROM python:3.7

RUN \
  apt-get update && \
  pip install torch numpy 
```

```docker-compose.yml
version: '2.3'

services:
  app:
    build: .
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=all
    volumes:
      - .:/workdir
    working_dir: /workdir
    tty: true
```

## 5. 出くわしたエラー:eyes:
#### 1つ目 unknown flag: --gpus
19.03以降にアップデートする
[Githubのissue](https://github.com/NVIDIA/nvidia-docker/issues/1165)を参考にしました。

```
sudo apt-get install docker-ce-cli
``` 
#### 2つ目 Unknown runtime specified nvidia
dockerの再起動で解決

```
sudo systemctl daemon-reload
sudo systemctl restart docker
```
[GitHubのIssue](https://github.com/NVIDIA/nvidia-docker/issues/838)を参考にしました

## 感じたこと
- nvidia-docker-composeを使う選択肢もあったけど、公式じゃないので敬遠しました
- 19:03以降で、nvidia-docker2以外を使って、docker-composeする方法があったら、誰か教えてください。
- 本当にdockerを理解したいなら、ドキュメントやrelease noteを読まないといけないなと、

以上、最後まで読んでいただき、ありがとうございました。