[AWS / EC2 / CUDA] GPU対応のEC2上で、CUDA入りDockerイメージを動かす (DEPRECATED)


# 0. 🚧🚧注意事項🚧🚧


以下の通り、 **nvidia-docker** はすでに廃止されてました (2024.1.22 らしい)

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

そのため、この記事には古くて使えない箇所が含まれています。途中までは参考になると思うのですが、 `nvidia-docker` という単語やコマンドが登場するところからは使えませんので、ご注意ください。


# 1. 配置状況
## 1-1. Hostマシン(EC2)にインストールするもの

- docker - [公式インストール手順](https://docs.docker.com/engine/install/)
- nvidia-driver - [公式インストール手順](https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html#runfile)
- ~~nvidia-docker~~ nvidia-container-toolkit - [公式インストール手順](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)


## 1-2. Docker上にあればよいもの

- CUDA
- (cuDNN)
- (python3)


# 2. Environment

||Information|
|:-:|:--|
|EC2 instance type|p2|
|GPU|Tesla K80|
|docker|20.10.17|
|docker image|nvidia/cuda:11.4.1-cudnn8-devel-ubuntu20.04|
|nvidia-driver|470.141.03|
|~~nvidia-docker~~|~~2.11.0~~|
|NVIDIA Container Toolkit|???|


# 3. install方法
## 3-1. Hostマシン側

### 3-1-1. Docker

[dockerは公式ドキュメントの通りにインストール](https://qiita.com/siruku6/items/d54ffc67e7dd130bb275#1-1-host%E3%83%9E%E3%82%B7%E3%83%B3ec2%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E3%82%82%E3%81%AE)しました。
他にいくらでも記事があるので省略。


### 3-1-2. nvidia-driverのバージョンを確認

次に、どのバージョンの`nvidia-driver`をインストールすればよいかを、以下のサイトで確認します。

https://www.nvidia.co.jp/Download/index.aspx?lang=jp

`nvidia-driver`のどのバージョンを使えばよいかは、**利用するGPUの種類**によって違います。
たとえば私はEC2の`p2`マシンを使っていたのですが、以下のコマンドでGPUの種類を確認してみると、tesla K80が載っていることがわかりました。

```bash
$ lspci | grep -i nvidia
00:1e.0 3D controller: NVIDIA Corporation GK210GL [Tesla K80] (rev a1)
```

その場合は、以下のようにセレクトボックスを選択して、検索ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/9373fa86-7daa-20a1-8192-dae336471198.png)

すると以下のように、`470.141.03`というバージョンのnvidia-driverを使うのが適切だと表示されました。

![2022-09-08_13h02_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/63114c15-7c18-cfac-ebac-13c209c045e8.png)

nvidia-driverはコマンド経由でインストールするので、ここでダウンロードボタンを押す必要はありません。


### 3-1-3. nvidia-driverインストール

公式ドキュメントの「[2. Runfile Installers](https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html#runfile)」と書かれているところに従ってやりました。

#### 事前準備

1. **Pre-Installation Requirement**  
上記公式ドキュメントの「1.1. Pre-Installation Requirements」をまだ実行していない方は、先にやっておいた方がいいかもしれません。
2. **`nouveau`無効化**  
`nouveau`というdriverが既にインストールされているマシンでは  
[この記事](https://qiita.com/ohta6/items/684b9ecd4d67a52e5a7f#%E5%85%AC%E5%BC%8F%E3%81%8B%E3%82%89%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89)や[この記事](https://qiita.com/daikumatan/items/26039fc23edabf76a9c4#21-%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AE%E5%81%9C%E6%AD%A2)に書かれているような方法で`nouveau`を無効化しておくとよい。  
`nouveau`が動いているかどうかは以下のコマンドで確認できるので、何か表示されたら無効化を先に行っておこう。

```bash
$ lsmod | grep -i nouveau
```


#### インストール開始

公式ドキュメントの`2. Runfile Installers`に従ってコマンドを実行していきます。

`nvidia-driver`のインストール時は、シェル上にUIっぽいものが出現して、対話的にインストールを進めることになる。
以下のような感じ。

```bash
$ sudo sh ./NVIDIA-Linux-x86_64-470.141.03.run ..............
Verifying archive integrity... OK
Uncompressing NVIDIA Accelerated Graphics Driver for Linux-x86_64 470.141.03..................................................
```

もうちょっと待つと、以下のようなUIが出現する。
※`teraterm`上で上記コマンドを実行した場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/08a0e072-aada-c9f2-446e-ecd16c39252f.png)

ここでは、キーボードを使って対話的にインストールを進める感じになる。


### 3-1-4. ~~nvidia-docker~~ nvidia-container-toolkit インストール

nvidia-container-toolkitも[公式のインストール手順](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)に従ってインストールしました。
コマンドひたすら打つだけ。私は全部コピーandペーストでも正常にインストールできました。

Dockerコンテナ内じゃなくて、ホストマシン(EC2)側にインストールしてねo(｡＞∆＜)o

## 3-2. Docker側の準備

`CUDA`と`cuDNN`については、これらがインストール済みの専用docker imageがあるので、それを利用しました。

### 3-2-1. CUDAバージョン選択

[先ほどのnvidia-driverのバージョン確認の画面](https://qiita.com/siruku6/items/d54ffc67e7dd130bb275#3-1-2-nvidia-driver%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E7%A2%BA%E8%AA%8D)では、tesla K80を選択するとCUDAバージョンについては11.4までしか選べませんでした。

tesla K80は若干古いんでしょうかね。
少なくとも、あの画面で選択可能なCUDAバージョンのうちのどれかを選ぶのが良さそうです。

...という経緯から、CUDAのバージョンは11.4系にしました。


### 3-2-2. Docker image選択

選択可能なdocker imageはここで探しました。

https://hub.docker.com/r/nvidia/cuda

私の場合は、CUDA 11.4系で、更にcuDNNを使いたいのと、なるべく新しいUbuntuにしておきたかったので、`nvidia/cuda:11.4.1-cudnn8-devel-ubuntu20.04`を選びました。

### 3-2-3. Dockerfile作成

そして、こんな感じでDockerfileを作成すればOK。

```Dockerfile:Dockerfile
FROM nvidia/cuda:11.4.1-cudnn8-devel-ubuntu20.04

...
```

cuDNNが不要な場合は、cuDNNなしのイメージもあるっぽいので、それを利用しよう。
あとはいつも通りDockerをbuildするだけ。


# 4. install結果の確認

## 4-1. nvidia-driverのバージョン確認

これはホストマシン側(EC2)で実行します。
nvidia-driverはEC2側にインストールしましたよね？|･ω･`)ｺｿｯ

```bash
$ cat /proc/driver/nvidia/version
NVRM version: NVIDIA UNIX x86_64 Kernel Module  470.141.03  Thu Jun 30 18:45:31 UTC 2022
GCC version:  gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
```

## 4-1. ~~nvidia-dockerのバージョン確認~~

~~これもホストマシン側(EC2)で実行。
nvidia-dockerもEC2側にインストールしましたよね？~~

多分今は、こんな nvidia-docker などというコマンドはなくなっているはず|･`ω･´)ﾁﾗﾘｯ

```bash
$ nvidia-docker version
NVIDIA Docker: 2.11.0  # <----- ここに１行追加されてる
Client: Docker Engine - Community
 Version:           20.10.17
 API version:       1.41
 Go version:        go1.17.11
 Git commit:        100c701
 Built:             Mon Jun  6 23:02:57 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.17
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.17.11
  Git commit:       a89b842
  Built:            Mon Jun  6 23:01:03 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.8
  GitCommit:        9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

---

# 🚧🚧以降は工事中🚧🚧

[nvidia-docker](https://github.com/NVIDIA/nvidia-docker) がなくなったみたいなので、この記事は今は古くて使えないと思われます。もし EC2 で環境構築する事があったら、更新したいと思います。

## 4-3. 全体の動作確認

これまでインストールしてきたものは相互に関連し合っているので、全体が正常に動くかを確認します。
以下のコマンド実行前に、docker buildしておくとよいです。

~~`nvidia-docker`~~ を実行する必要があるので、以下のコマンドもホストマシン側(EC2)で実行しますよ！｜電柱｜∀゜`)ジー

```bash
# docker image名は各自で変更してね
$ nvidia-docker run --rm --gpus all nvidia/cuda:11.4.2-cudnn8-devel-ubuntu20.04 nvidia-smi
Thu Sep  8 04:39:31 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.141.03   Driver Version: 470.141.03   CUDA Version: 11.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00000000:00:1E.0 Off |                    0 |
| N/A   46C    P0    60W / 149W |      0MiB / 11441MiB |    100%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
```

上記のような表が表示されれば、無事動いているということです。


# 5. ~~起動コマンドの注意点~~

```bash
# ダメだった...
$ docker run -it ....

# こうすればOK
$ nvidia-docker run -it ....
```

上記の通り、**いつも通りdockerコマンドを使うと、私の場合はGPUが認識されませんでした**。要注意です。`nvidia-docker run ...`としておくのが良さそう。

(+α) 皆さんなら大丈夫だと思いますが、nvidia-dockerをインストールした後に `sudo systemctl restart docker` くらいは実行して、docker daemonの再起動はしておいた方がいいかもしれません。


# 6. 思ったこと

これだと、`docker-compose`と連携させるの難しいな...

んーーーいや、最近はdockerのアップデートによってコマンドの打ち方が変わって、`docker compose`みたいな打ち方に変わったから、`nvidia-docker compose up`とかできるのかも....？

未確認ですが、良い方向に進んでいると期待しています。