【GPU環境構築設定】Ubuntu(20.04)+Visual Studio Code+GitHub+Docker+NVIDIA Container Toolkit+PyTorch

# 初めに
Ubuntuの再インストールをせざるを得ないときや, 新しい環境でまた初めからセットアップが必要な際にある程度の環境をスピーディに構築できるように備忘録として書いています.
ゴールはdockerコンテナ上でGPUを使用することですが, 周辺的な知識であるGitHubやエディタ(VSCode)などに触れつつ, 1から簡単なDeep Learning環境を構築することを目指します.

対象者のレベル感としては, "研究室配属されたばかりでUbuntuマシン渡されたけど環境構築どうすればいいの？と迷っている"という人あたりには役立つのかなと思います.

大まかな内容としては以下の通りです.

0. [USキーボードを使っている場合の設定](#1-usキーボードを使っている場合)
0. [Visual Studio Codeの設定](#2-visual-studio-code-編)
    0. [key config](#key-config)
    0. [ssh](#ssh)
    0. [プラグイン](#プラグイン)
0. [GitHubの設定](#3-github-編)
    0. [Install](#install)
    0. [GitHubとの連携](#githubの連携設定)
    0. [Gitでよく使うコマンド](#gitでよく使うコマンド)
    0. [別マシンや別環境でブランチ共有](#別マシンや別環境でgitのブランチを共有したいとき)
0. [Docker + NVIDIA Container Toolkit + PyTorch](#4-docker--nvidia-container-toolkit--pytorch-編)
    0. [nvidia driver のインストール](#nvidia-driverのインストール)
    0. [docker のインストール](#docker-engine-のインストール)
    0. [NVIDIA Container Toolkitのインストール](#nvidia-container-toolkitのインストール)
    0. [pytorch公式のimageを使ってのコンテナ作成し, コンテナ上でGPUを扱う](#docker環境構築)
    0. [Dockerでよく使うコマンド](#その他コマンド)
0. [その他Tips](#5-その他tips)
    0. [コンテナ上でのOpenCVのエラー対処](#opencvを使う)



Ubuntuは以下のバージョンです. 他のバージョンでも大方変わらないと思います.

```
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
```

完全に個人の備忘録ですが, なにか参考になれば幸いです.

# 1. USキーボードを使っている場合

個人的これが一番早い設定.

https://blog.kapiecii.com/posts/2020/05/10/ubuntu20-04-mozc-setting/



# 2. Visual Studio Code 編
### install 
https://code.visualstudio.com/

### Key Config
普段MacOSを使っている場合 ```command``` などがUbuntuでは存在しないため, デフォルトのショートカットが異なります.　ですので, key mappingを自分で設定し直すと快適です.
VSCodeを開いて  ```Ctrl+Shift+P```　と入力し
```preferences: Open Keyboard Shortcuts```を選択.
![Screenshot from 2021-07-12 16-03-35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/04ef03a4-d45d-14ef-51b5-597697cbed1a.jpeg)![Screenshot from 2021-07-12 16-03-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/ea21add5-e8ec-1792-f40b-fa433a8fb6d1.png)

開いた画面で自分の好きなようにキーバインドを設定できます.

また, ```preferences: Open Keyboard Shortcuts (JSON)```　からも設定が可能で(前述の方法で設定した場合自動で記述されます), 自分で設定したJSONファイルを保存しておくと, 新しい環境でもJSONを置くだけですぐにキーバインドを設定できるので, バックアップを取っておくことをおすすめします.

![Screenshot from 2021-07-12 16-04-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/33d33b9c-80a8-12f3-04aa-7f1bb0bdd5cb.png)

### SSH
VSCodeのプラグインを用いて簡単にSSHが可能なので記述しておきます.

```Extentions```  (サイドバー or ```Ctrl+Shift+X``` )を開き, ```SSH```と検索します.
```Remote - SSH``` をインストールします. 

![スクリーンショット 2021-07-12 17.58.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/f657afe8-95ca-9eba-f5ed-5eff05472f42.png)


左下の緑のアイコン```Open a Remote Window```  をして, ```Open SSH Configuration File``` を選択します.

![スクリーンショット 2021-07-12 17.27.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/4143bb5f-f7ed-ea6a-c80a-16f4dc2b12ae.png)

![スクリーンショット 2021-07-12 17.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/ac585f29-e9a3-b6ed-0af3-51ef937e71df.png)

適当なconfig fileにssh先の情報を記述します.

```~/.ssh/config
Host <HOST> #好きに名前をつける
  HostName <IP or HostName>
  User <USER NAME>
  Port <PORT NUMBER>
```

設定後に左下の緑のアイコン```Open a Remote Window``` を選択し, 設定したHostに接続することができます. aliasを書いたりするより楽なのでおすすめです.

### プラグイン
VSCodeには快適にコーディングするため, 便利にするための様々な拡張機能を導入することができます.
色々とデフォルトのサポートになったりアップデートされたりしているので, ```VSCode おすすめプラグイン``` など調べて, 自分に合いそうなものをインストールするが良いと思います.
一部参考程度に紹介.

* Bracket Pair Colorizer 2
カッコに色がつく.

* Japanese Language Pack for VS Code
日本語になる.

* Jupyter
jupyter notebookが読み込める.

* Markdown PDF
マークダウンをPDFに変換できる.
***余談：markdownのVisualizeはUbuntu上だと```Ctrl+Shift+V``` で可能***

* Partial Diff
選択部分のどこが異なるか見つける. diffコマンドの一部分バージョン.

* Trailing Spaces
末尾にあるスペースを削除する.

* vscode-icons
なんかアイコンがかっこよくなる.

* zenkaku
全角スペースをハイライトしてくれる.

# 3. GitHub 編
## GitHubの連携設定

### install

```
sudo apt install git
```

### ユーザーアカウント設定
GitHubで登録している自分のアカウント情報を設定.

```
git config --global user.name <USER NAME>
git config --global user.email <EMAIL ADDRESS>
```

設定の確認

```
git config --list
```
以下のように表示されればOK. (今回は自分の設定例です.)

```
user.name=Hoge
user.email=hoge@icloud.com
```


### 鍵の作成

```
ssh-keygen -t rsa -C <EMAIL ADDRESS>
```

```~/.ssh/id_rsa``` , ```~/.ssh/id_rsa``` が作成されます.


```-f <id_rsa_file_name>```
で鍵の名前を指定が可能.

### Github上での設定

```
cat ~/.ssh/id_rsa.pub
```
で表示された鍵をコピーして
```GitHubの右上の自分のアイコン``` -> ```settings``` -> ```SSH and GPG key``` -> ```New SSH key``` の ```key``` にコピーした鍵を貼り付け. ```Title``` にはマシンの名前とかを入れとくと良いと思います.

![スクリーンショット 2021-07-12 17.32.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/affb00b8-0085-da55-d8f4-2435a51f256e.png)

![スクリーンショット 2021-07-12 17.34.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/05034fa4-bbb5-0ce8-2987-bc34dac6e842.png)



```
ssh -T git@github.com
```

で接続できていればOK.

### \* 鍵の名前を指定した場合の注意点
```~/.ssh/config``` を作成して以下のように名前を指定する必要があります.

```~/.ssh/config
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/<your rsa name>
  User git
```

## Gitでよく使うコマンド
* ブランチを作成して切り替え
```git checkout -b <BRANCH NAME>```

* ブランチの確認
```git branch```

* add
```git add <FILE>```

* fileの変更などの確認
```git status```

* commit
```git commit -m "comment"```

* 現在のbranchにpush
```git push origin HEAD ```

## 別マシンや別環境でgitのブランチを共有したいとき
あとから新たなマシンで```dev/xxx```などの```master or main```とは異なるすでに作成されているブランチを共有したい場合があると思います.
以下のようにマージすることで作業中のbranchの共有が可能.

```
git clone <HTTPS or SSH>
git checkout -b <すでに作成されている共有したいブランチname>
git fetch origin
git merge origin/<すでに作成されている共有したいブランチname>
```

# 4. Docker + NVIDIA Container Toolkit + PyTorch 編

## Nvidia Driverのインストール

### CUI ver. 
https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu

ここの```Select Target Platform```で自分の環境を入力するとinstallation instructionsが表示されるのでそれに沿ってインストール.

\* 以下のコマンドでubuntuのplatformの確認が可能.

```
cat /etc/lsb-release 
```

最新版のインストール.
  
```
sudo apt-get -y install cuda
```

### GUI ver.
```アプリケーション``` -> ```LivePatch``` -> ```追加のドライバー```
自分の環境にあるドライバーをインストール.

## Docker Engine のインストール
https://docs.docker.com/engine/install/ubuntu/

ここの```installation methods```に沿ってインストールします.

```
sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
```
### \* version指定する場合
利用可能なバージョンの確認.

```
apt-cache madison docker-ce
```

バージョンを指定してインストール.

```
sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
```

hello-world imageを使ってDocker Engineの確認.

```
sudo docker run hello-world
```

以下のように表示されたらOK.

```
Hello from Docker!
This message shows that your installation appears to be working correctly.
```

## NVIDIA Container Toolkitのインストール

### NVIDIA Container Toolkitとは

https://github.com/NVIDIA/nvidia-docker/tree/master#quickstart

GPUで高速化されたDockerコンテナの構築と実行を可能にします. このツールキットには, コンテナ・ランタイム・ライブラリと, NVIDIA GPUを活用するためにコンテナを自動的に設定するユーティリティが含まれています.
![5b208976-b632-11e5-8406-38d379ec46aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426156/809bc97e-e9b1-2f61-c6b0-6492a54c776d.png)

### installation

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

ここの```Setting up NVIDIA Container Toolkit```に沿ってインストールします.

```
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-docker2
sudo systemctl restart docker
```
確認

```
nvidia-container-cli info
```

## Docker環境構築
###はじめに
予めdockerのグループに追加しておくとsudoをつける必要がないのでおすすめです. (要reboot)

```
sudo gpasswd -a <user name> docker
```

### imageの作成
### 公式のdocker imageを用いる場合
https://github.com/pytorch/pytorch

https://hub.docker.com/r/pytorch/pytorch/tags?page=1&ordering=last_updated

dockerのイメージをpullしてくる.　ここではpytorch公式のものをpullします.

```
sudo docker pull pytorch/pytorch
```

以下のコマンドで```pytorch/pytorch```のリポジトリがあるか確認する.

```
sudo docker images
```

### Dockerfileからbuildする場合
Dockerfileのあるディレクトリで

```
sudo docker build .
```
確認

```
sudo docker images
```
名前をつける


```
sudo docker tag <IMAGE ID> <IMAGE NAME>:<TAG>
```

\<TAG>を指定しない場合```latest```となる.

### コンテナの作成
```-v ~/directory:/directory``` でコンテナからホスト側にアクセスできるディレクトリを指定. ```マウントしたい場所:docker側の場所``` .
```$PWD:$PWD```にするとコンテナからホスト側カレントディレクトリにアクセスできる.
　複数指定したい場合は, ```-v ~/directory:/directory -v ~/directory:/directory``` のようにオプションを複数回つければ可能.
```--gpus all```でGPUコンテナを実行できる.
```--name <CONTANAIR NAME>``` でコンテナに名前をつける.
```-p```でポート指定.

```
sudo docker run -it--gpus all -v ~/directory:/directory —name <CONTANAIR NAME> <IMAGE NAME>:<TAG>
```


```e.g.
sudo docker run -it --gpus all -v $PWD:$PWD --name pytorch_env pytorch/pytorch
```

```nvidia-smi``` が動けばOK.

\* 以下のようなエラーが出たら

```
docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]].
ERRO[0000] error waiting for container: context canceled 
```

デーモンの再起動を行う

```
systemctl restart docker.service
```
もしくは下記URLを参照.

https://cocoinit23.com/docker-gpu-error-response-from-daemon-linux-runtime-spec-devices-could-not-select-device-driver-with-capabilities-gpu/

## その他よく使うコマンド

コンテナをスタートする
```sudo docker start <CONTANAIR NAME>```
コンテナに入る
```sudo docker exec -it <CONTANAIR NAME> bash```
動いているコンテナを表示
```sudo docker ps```
コンテナをすべて表示
```sudo docker ps -a```
コンテナ削除
```sudo docker rm <CONTANAIR ID>```

### 5. その他Tips
## OpenCVを使う

以下のエラーへの対処法.

```
ImportError: libGL.so.1: cannot open shared object file
```

以下のコマンドを実行. 必要であればDockerfileに書いておくと楽になります.

```
apt-get update && apt-get upgrade -y
apt-get install -y libgl1-mesa-dev
```