DockerでGPU+TensorFlow/PyTorchの環境構築した時のメモ

:::note
この記事は公開時からほぼ更新していません。単に記録のために残してあります。2025年現在は環境が大きく変わっているので参考にするのはおすすめしません。
:::

GPU付きサーバのTensorFlow/PyTorchの環境構築して困ったところを中心にメモ。
Dockerは聞いたことあったけど全く使ったことない人です。

# 2024-11-20追記

最近はVSCode経由でDev Containersを使ってコンテナを管理すると楽。
特にワークスペースごとに異なるコンテナイメージを紐づけたい場合に便利。

# 2021-12-17追記

Singularityの方が圧倒的に楽だった。Dockerイメージも流用可能。
Dockerだけならrootlessモードを使ってみたい。

https://qiita.com/mkt3/items/b9f86f5ddf9eb0f43608

# なぜGPUサーバの環境構築にDockerを使うのか

風の噂によるとGPUドライバ・ライブラリ周りの互換性が面倒らしい。
Nvidia Container ToolkitでDockerイメージとして入れると幸せになれると聞いた。

https://qiita.com/tkusumi/items/f275f0737fb5b261a868


# OS・ハードウェア

- OS: Ubuntu 20.04.3
- CPU: AMD Ryzen (Zen 2)
- GPU: Nvidia Geforce (Ampere)


# Nvidiaドライバのインストール

サーバのベンダーが入れてくれていたので流用。
Driver Version: 470.86


# Dockerのインストール

aptでいれた。

```bash
$ docker --version
Docker version 20.10.12, build e91ed57
```


# Nvidia Container Toolkitのインストール

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html

公式で特に困らなかった。

```bash
$ nvidia-container-cli -V
cli-version: 1.7.0
lib-version: 1.7.0
# 以下略
```


# Dockerの概要・基本操作

https://qiita.com/wMETAw/items/34ba5c980e2a38e548db

https://qiita.com/etaroid/items/b1024c7d200a75b992fc



# Docker操作でsudoが必要になるのを回避

ユーザをDockerのグループに追加すればsudoは不要。

https://www.wantanblog.com/entry/2020/02/01/013958

```bash
$ sudo usermod -aG docker ${ユーザ名}
```


# docker runのオプション数削減

Dockerfileとdocker-composeを使えば良いらしい。
イメージは固定で引数部分で色々面倒ならdocker-composeだけで済みそう。

https://qiita.com/etaroid/items/88ec3a0e2d80d7cdf87a

https://qiita.com/soushiy/items/0945bcbc7ecce4822985

https://docs.docker.jp/engine/reference/builder.html

https://docs.docker.com/compose/gettingstarted/


# docker-composeのインストール

https://docs.docker.com/compose/gpu-support/

なぜかうまく行かないと思ったら、
aptでインストールしたdocker-composeが古すぎてうまく行かなかった。
見てたマニュアルはv1.27以降のみの記述。

```bash
$ sudo apt install docker-compose
$ docker-compose --version
docker-compose version 1.25.0, build unknown
$ sudo apt purge docker-compose
```

https://docs.docker.com/compose/install/

公式情報から最新版をcurlで入れた。

```bash
$ docker-compose --version
docker-compose version 1.29.2, build XXX
```


# Dockerにroot以外のユーザで入りたい

https://qiita.com/acro5piano/items/8cd987253cb205cefbb5

docker-compose.xmlを以下のように用意。
イメージはNvidia Container Toolkitのインストール時に試したnvidia/cuda:11.0-baseを利用。

```xml:docker-compose.xml
version: '3'
services:
   test:
      image: nvidia/cuda:11.0-base
      volumes:
         - /etc/passwd:/etc/passwd:ro
         - /etc/group:/etc/group:ro
      user: "${UID}:${GID}"
```

/etc/passwdとgroupはマウントしないとコンテナから読めなくて怒られる。
また、UIDとGIDは環境変数でないとdocker-composeが読めないっぽい。

https://github.com/docker/compose/issues/2380

試した環境だとUIDはシェル変数だけど環境変数ではなく、GIDはそもそも定義されてなかった。
以下のようにするとうまく行った。最初の2行をbashrc等に書いておく。

```bash
$ export UID
$ export GID=$(id -g)
$ docker-compose run test /bin/bash
$ docker-compose down
```


# Nvidia公式TensorFlowイメージでメモリ不足の警告

https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tensorflow

https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/

リリースノートを見てドライバのバージョンに合うもの(ここではnvcr.io/nvidia/tensorflow:21.10-tf2-py3)を使う。

```bash
$ docker run --gpus all -it --rm nvcr.io/nvidia/tensorflow:21.10-tf2-py3

================
== TensorFlow ==
================
# (中略)

NOTE: The SHMEM allocation limit is set to the default of 64MB.  This may be
   insufficient for TensorFlow.  NVIDIA recommends the use of the following flags:
   docker run --gpus all --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 ...

# (略)
```

共有メモリが足りないらしい。
docker-compose.xmlでオプションを指定。

```xml:docker-compose.xml
version: '3'
services:
   tensorflow:
      image: nvcr.io/nvidia/tensorflow:21.10-tf2-py3
      volumes:
         - /etc/passwd:/etc/passwd:ro
         - /etc/group:/etc/group:ro
      user: "${UID}:${GID}"
      ipc: host
      ulimits:
         memlock: -1
         stack: -1
      deploy:
         resources:
            reservations:
               devices:
                  - capabilities: [gpu]
```


# Nvidia公式PyTorchイメージ

https://catalog.ngc.nvidia.com/orgs/nvidia/containers/pytorch

ほぼtensorflowと同じ。


# 検証環境まとめ

- OS: Ubuntu 20.04.3
- CPU: AMD Ryzen (Zen 2; x86_64)
- GPU: Nvidia Geforce (Ampere)
- Nvidiaドライバ: 470.86
- Docker: 20.10.12
- Nvidia Container Toolkit: 1.7.0
- docker-compose: 1.29.2


# 雑感

- 確かに相当スムーズに環境構築出来た。
  - Dockerの学習コストを恐れてたが環境構築だけなら高度な知識は不要そう。
- 個人サーバだからこの設定で行けるが共用サーバだと困りそう。
  - 非管理者がコンテナ操作するならDockerのrootlessモードがよさそう。
  - ライブラリ導入を楽にするのが目的だしSingularityの方が用途に合ってるかも。
  - 複数人が利用するならDockerでJupyterHubサーバを立ててしまうのも検討したい。
- 個人サーバなら素直にライブラリ群入れても良さそうな。
  - Pythonライブラリ間の依存性解消だけを目的とするならconda/pipで仮想環境でも良さそう。
  - Python以外でもGPU周りの環境構築が必要だったので学習コストを払ってもコンテナで運用中。