深層学習用のUbuntuサーバーのDocker初期設定メモ


VPSとかクラウドで深層学習用のdocker環境を設定するときのメモ。
webでデプロイするならクバネテス流行りですし、1年くらい前に自分の現場でもクバネテス、dockerの環境に総入れ替えされました。
今いじってるdockerイメージってのをプライベートリポジトリに保存することができる。gcpやazure、awsで各社提供してるので使うときはそっちのドキュメント参照。

今年は基盤側も勉強していきたい。

随時更新。


# インストール時の注意！！！

これは大事。cuda系の環境を触るときはPCが死ぬ覚悟が必要。（何度も環境壊した）

# 最新情報を使おう 

qiitaやブログを見たときに情報が古い場合があるので注意。


(エバンジェリスト情報)[https://qiita.com/ksasaki/items/b20a785e1a0f610efa08]
や公式が正。


### 新規でPCに環境を作る場合

一番初めに下記のことを確認してから、その後の作業をしよう。

- ubuntuのバージョン最新へ
例えばubuntu18を使うのであれば、初めに18にしとくこと。cuda入れた後に14から18にすると何か問題起きるかもしれない。
- cudaドライバとか設定
nvidia-smi通るように設定。
- nvidia-docker入れる
- 一回PCを終了して再度起動できることを確認(大事)
画面真っ黒になる現象があり得るので、先にここまで確認してから学習回すこと。

### 元々あるPCに環境を作る場合

元のデータバックアップしてから作業してください。
大事なデータ消えて泣いてるところを見たくないです。


# dockerで何が嬉しい？

dockerはちっちゃいos。dockerがあると嬉しいことがある。
作ったwebアプリを運用サーバーで動かすときにする作業をデプロイと言ってる。
例えばこのデプロイでもdockerがあるとメリットがある。過去は手動でデプロイしている時期があった。またレガシーな環境の場合まだこの形式をとってる場合も多い。その後に物理サーバーに対して自動でデプロイできる機能を持ったansibleなどのライブラリがあった。gitにソースをあげると自動でjenkinsがビルドして、エラーがなかったら自動でansibleが運用サーバーにデプロイしたりしていた。
物理サーバーの上にdockerを載せることで環境を分けることができる。vmとの違いはosの上にosが載ってるか、あるいはカーネルの上にosが載ってるかの違い。dockerはカーネルの上に連結されているので、vmより軽量になる。

「デプロイ手法」
・手作業でデプロイ
・ansible jenkins自動デプロイ
・dockerfile で手動
・docker-compose upでデプロイ
・kubernetes使う

例えば運用サーバーがオンプレで１台の運用サーバにcuda8が動いてるとします。この状態でcuda9にあげたい場合はサーバーを1回止めるか、１個物理サーバーを増やす必要があります。

Aサーバー：運用　cuda8 ubuntu14 pytorch 0.0.1
Bサーバー：開発　cuda8 ubuntu16 pytorch 0.4.1

もしdockerで運用されていれば今のコンテナ（動いてる任意の単位のdokcer）を保存しておいて、新しいdockerを入れてcuda8のdockerコンテナとcuda9のdockerコンテナを共存させることができます。あとは好きなタイミングで切り替えをすれば運用環境を新しくすることができます。

保存：contena1：pytorch 0.0.1
Aサーバー：運用　：contena2：pytorch 0.4.1
Bサーバー：開発　：contena1：pytorch 0.4.1



# ユーザー追加（任意）

```
sudo gpasswd -a user1 sudo
```

# 鍵の生成（任意）

必要な場合はローカルで鍵生成する。
鍵がすでにあるときは-fで任意ディレクトリに生成してね。
パスフレーズは11文字以上にすること
↑短いと総当たり攻撃で突破されるよ？

```
ssh-keygen -t rsa -f conoha
scp 鍵名.pub ユーザー名@IPアドレス:~/.ssh/authorized_keys
```

オプションの詳細
https://pig-log.com/ssh-keygen-command/


.sshフォルダとauthorized_keysファイルがなければ作ってね。
authorized_keysに公開鍵が入る。

```
ssh -i ユーザー名@IPアドレス
```

で入れることを確認

ルートになっておく

```
su
```

ユーザー切り替え

```
sudo su [ユーザー名]
```

バックアップ

```
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org
```

# sshd_configを変更 [VPSの時]

クラウドの場合は設定画面で設定する。


ポートかえる
22→
49513〜65535 


```
emacs /etc/ssh/sshd_config


- Port 22
+ Port xxx # ポート変更

- PermitRootLogin yes
+ PermitRootLogin no #rootログインさせないよ

- PubkeyAuthentication no
+ PubkeyAuthentication yes #公開鍵ログイン

- PasswordAuthentication yes
+ PasswordAuthentication no #パスワードログインさせないよ
```

再起動で反映

```
service sshd restart
```



# ファイヤーウォール [VPSの時]

外部から接続するときは別途VPNはるべき。

```
sudo ufw allow <ssh port> #sshの22から変更した任意のポーと指定。
sudo ufw allow 80   # http
sudo ufw allow 443  # https
sudo ufw allow from 192.168.1.0/24 to any port ssh #IPを指定してssh接続のみ許可
sudo ufw enable #有効化
sudo ufw status #確認
```

クラウドの場合は設定画面で設定する。

- azureの静的IP制限

https://docs.microsoft.com/ja-jp/azure/app-service/app-service-ip-restrictions

- Azureでスナップショットをとる

キャプチャの機能を使うが、一旦仮想マシンを閉じでイメージを作ることになる。
そのあと仮想マシンは削除して、キャプチャをとったイメージから仮想マシンを再作成する必要がある。
ちょっとめんどい。

https://blogs.technet.microsoft.com/jpaztech/2017/11/21/cannot-start-vm/

- Azureの/mntが異常にでかいんだけど。。。

無理やりパーティションずらせたりできないのかなぁ。。
https://qiita.com/409_nu/items/69c5564794ff6fdc0fd6

/mntは一時ファイル領域らしいので毎回消えるんだよ。その領域すごいでかいから普通に使いたいよ。

# docker

時代はdocker。

docker pullしてdocker iamgesで確認。
docker run -itしてdocker ps -aでプロセス確認。
docker exec hoge /bin/bashで入る。
抜けるときはctrl+dでUp状態で抜ける。
docker ps -aでプロセスがUpになってなかったらdocker start hogeする。
こんな感じなんですけど、他の記事も参照しながらやって見てください。
ではdockerを入れて行きます。

もっと奥が深いですが、単純な操作の説明でした。

```:Ubuntu
#docker入れる
sudo apt-get update
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common \
    emacs
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```



## Docker Community Edition

```
#docker ce入れる
sudo apt-get update; sudo apt-get install docker-ce
```

動作確認

```
#dockerコンテナ動かす
sudo docker run hello-world #動作確認
#プロセス確認
sudo docker ps -a
#イメージの確認
sudo docker images
#コンテナ削除
sudo docker rm [contaner id]
#イメージ削除
sudo docker rmi [images id]
```

# dockerをsudoなしで動かす

これは任意です。sudoコマンド入れるのがめんどくさい場合にやる。

```
sudo groupadd docker
sudo gpasswd -a $USER docker
sudo service docker restart docker
exit
```

一旦出て入り直すといけた


# dockerに入る

docker psでコンテナがUpになってればexecでdockerコンテナに入れます。

```
#まずイメージからコンテナをrunする。
docker images
#imagesにあったimage idでrunする
docker run -it a10077ecbc3e
```

入ったらはじめに
apt-get update
しておかないとapt-get installできない。


コンテナに入ると自分はこの辺はデフォで入れる。

```
apt-get install python-pip python2.7 python2.7-dev python3 build-essential autoconf libtool pkg-config python-opengl python-imaging python-pyrex python-pyside.qtopengl idle-python2.7 qt4-dev-tools qt4-designer libqtgui4 libqtcore4 libqt4-xml libqt4-test libqt4-script libqt4-network libqt4-dbus python-qt4 python-qt4-gl libgle3 python-dev python-pip tree curl git emacs wget zip cmake
```

# docker-compose

dockerをまとめることができる。docker何個も立ち上げるようになってくると、composeを使わずにはいられない。


```:Ubuntu
curl -L https://github.com/docker/compose/releases/download/1.20.0-rc1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```



# ndivia docker

cuda使いたい場合はnvidia dockerを使います。nvidia dockerはバージョン２を使用します。
古い記事をみるとv1の内容だったりもします。


ドライバがない場合は入れる。この辺のバージョンが環境に合わない場合は１からOS入れなおしたりしてハマったこと何度もあり。。。
環境によっての差異を正直まだよくわかってません。

```
#ドライバ入れる
sudo apt-get install nvidia-384
sudo apt install nvidia-cuda-toolkit
sudo reboot
```

次にnvidia dockerのイメージを落とします。
nvidia docker cloudを使う方法とdocker hubを使う方法を記載します。

- nvidia docker cloudを使う場合

クラウドって名前だけど、ただのドッカーハブぽいやつ。

```
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \
sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | \
sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update
#v2です。
sudo apt-get install nvidia-docker2
#reload dockerd
sudo pkill -SIGHUP dockerd
```

クラウドって書いてるけど、ただのdocker file。クラウドじゃないよ。
https://ngc.nvidia.com/

bashでログインする。

```
docker login nvcr.io
```

user nameには$oauthtokenを入れて
keyにはapi keyを入れる。
Login Succeededと出るとOK。


```
#cuda通るのを確認できます
docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi
#イメージIDを指定してrunします (itはimageの指定)
docker run --runtime=nvidia -it a10077ecbc3e /bin/bash
```

指定して動かす場合。
大量のdockerfileが存在する。

```
CUDA 9.2 (EXPERIMENTAL)
9.2-base-ubuntu18.04 (9.2/base/Dockerfile)
9.2-runtime-ubuntu18.04 (9.2/runtime/Dockerfile)
9.2-devel-ubuntu18.04 (9.2/devel/Dockerfile)
9.2-cudnn7-runtime-ubuntu18.04 (9.2/runtime/cudnn7/Dockerfile)
9.2-cudnn7-devel-ubuntu18.04 (9.2/devel/cudnn7/Dockerfile)
...略
```

- docker hubから取得する場合


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

cuda8 ubuntu16.4を指定して起動する。

```
#イメージを取る
docker pull nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04
#nvccがないバージョン
docker run --runtime=nvidia --rm nvidia/cuda:8.0-runtime-ubuntu16.04 nvidia-smi
#nvcc付きのバージョン
docker run --runtime=nvidia --rm nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04 /bin/bash
#ホストpcとマウントしときたい場合はrunの時に入れとかないとダメだよ
#注意！！マウントがちゃんとされてるかは、コンテナ作成直後の段階で確認すること！そのまま先に進んだら、マウントできてないのに先に進んで後から全部作り直しもあり得る。
docker run --runtime=nvidia -it --name hoge_ver1 -v /home/miyamoto/hoge:/hoge 0b571ae4e7fc /bin/bash
```


# コマンドメモ


・コンテナのコミット

現在のコンテナをコミットしてイメージ化できます。

```
docker commit コンテナ名 リポジトリ名:タグ名
docker commit 479d1850503b pytorch:version3
```

・コミットしたimageをrunしたい

イメージからコンテナ化できます。

```
docker run --runtime=nvidia -it a10077ecbc3e /bin/bash
```


- tensorflow動かす。

```
sudo docker pull nvcr.io/nvidia/tensorflow:18.03-py3
```

nvidia-docker v2のtensorflowはエラー出てるように思う。
https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)


# docker-composeで使う

https://qiita.com/uni-3/items/f5911aaaa538b33f370f

# dockerメモ

・コンテナ内操作


```
docker attach [コンテナID]
or
docker exec -it [コンテナID] /bin/bash
or
docker start [コンテナID]
```



・コンテナからホストにコピー

```
docker cp [コンテナID]:/etc/hoge.txt hoge.txt
```

・ホストからコンテナにコピー

```
docker cp hoge.txt [コンテナID]:/etc/hoge.txt
```


- 一括コンテナ停止、一括コンテナ削除、一括イメージ削除

```
docker stop $(docker ps -q)
docker rm $(docker ps -q -a)
docker rmi $(docker images -q)
```

#Azure Container Registryを使用

Container Registryに保存すると便利。
使い方は下記。

https://docs.microsoft.com/ja-jp/azure/container-registry/container-registry-get-started-portal


docker imagesでREPOSITORY名を確認して指定。


```
docker run -it hoge.azurecr.io/hoge:v1 /bin/bash

docker run --runtime=nvidia -it hoge.azurecr.io/hoge:v1 /bin/bash
```

nvcc有りか無しかの情報源。
https://devtalk.nvidia.com/default/topic/1016258/cuda-setup-and-installation/cuda-8-0-in-docker-nvcc-not-found/



# その他
## sshエラー

ssh [your user id]@[your ip]

sshでエラーになるときは一旦削除する。

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:hogehoge.
Please contact your system administrator.
Add correct host key in /Users/hoge/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/hoge/.ssh/known_hosts:62
ECDSA host key for 1.1.1.1 has changed and you have requested strict checking.
Host key verification failed.
```



```
ssh-keygen -R [your ip]
```

# dockerエラー

コンフォリクトが起こった場合

```
Error response from daemon: conflict: unable to delete aebd66be3e22 (must be forced) - image is referenced in multiple repositories
```

```
docker rmi -f <IMAGE_ID>
```


# Specify CUDA_TOOLKIT_ROOT_DIR

PyTorchをsetup.pyインストールする時にハマったエラー。
要はcuda通ってないんですわ。

パスがとってない可能性とか。
https://discuss.pytorch.org/t/updating-pytorch-issues/13685/6

自分の場合はdocker使ってたので普通にnvccが通らないバージョン使ってたのが原因だった。


```
If you want nvcc, you should use 8.0-devel-ubuntu16.04.
The runtime images don't provide the compiler toolchain.

Alternatively, you could also "apt-get install -y cuda-core-8-0" from your own Dockerfile.
```

nvcc -Vが通ってnvidia-smiが通るのは前提ですよと。

https://devtalk.nvidia.com/default/topic/1016258/cuda-setup-and-installation/cuda-8-0-in-docker-nvcc-not-found/

その後には動くようになった。

```
wget https://github.com/pytorch/pytorch/archive/v0.1.12.zip
unzip v0.1.12.zip
cd hogehoge
sudo python setup.py install
```

g++のバージョンが合ってないで死ぬ可能性もあると思う。
その場合はバージョン切り替え可能。

```
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 10
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 30

```

https://askubuntu.com/questions/909588/switch-between-two-version-of-gcc?noredirect=1&lq=1


https://devtalk.nvidia.com/default/topic/995277/cuda-setup-and-installation/cuda-8-0-toolkit-install-nvcc-not-found-ubuntu-16-04/

https://github.com/torch/cutorch/issues/425

# azureのnvcc無いときのインストールで困ったとき

マーケットプレイスでnvidia系のパッケージ使って、アーキテクチャをncシリーズを選択。
んでnvccが無いってエラー出て入れようとしても全然入らんとき。

<b>
＠結論：マーケットプレイスで普通のubuntu選んでからncのパッケージ選ぼう。
</b>


```
sudo apt-get install nvidia-384
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package nvidia-384 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'nvidia-384' has no installation candidate
```



```
sudo apt install nvidia-cuda-toolkit
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 nvidia-cuda-toolkit : Depends: nvidia-profiler (= 7.5.18-0ubuntu1) but it is not going to be installed
                       Depends: nvidia-cuda-dev (= 7.5.18-0ubuntu1) but it is not going to be installed
                       Recommends: nvidia-visual-profiler (= 7.5.18-0ubuntu1) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
```

この手のエラーでapt removeとか諸々してもうまくいった試しがない。もぉインスタンス作り直すが正。
この辺とか戦ったけど無理。

```
sudo apt-get remove cuda*
sudo apt-get remove nidivia*
```

https://gist.github.com/bzamecnik/b0c342d22a2a21f6af9d10eba3d4597b
https://unix.stackexchange.com/questions/218163/how-to-install-cuda-toolkit-7-8-9-on-debian-8-jessie-or-9-stretch


#ubuntu18のエラー

いつ解消するかわかんないけど、ubuntu16入れようね。

```
$ nvidia-smi
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running."
```

https://qiita.com/bohemian916/items/7637b9b0b3494f447c03

# GPU使わないでCentOS


```:Centos
#Docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker
#CentOS
sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```

# jetsonでdocker

結論あんまりおすすめしない。armの問題もあり結構やりずらい。

(install仕方)[https://blog.hypriot.com/post/nvidia-jetson-nano-upgrade-docker/]


# 参考
https://blog.sky-net.pw/article/103
https://qiita.com/kooohei/items/f0352f408056861a8f74
https://qiita.com/RyoMa_0923/items/9b5d2c4a97205692a560
https://github.com/portainer/portainer/issues/497
https://qiita.com/grgrjnjn/items/8ca33b64ea0406e12938
https://pig-log.com/ssh-keygen-command/
https://qiita.com/jqtype/items/e394fb9e027892e9a2a4
https://dev.classmethod.jp/tool/github-ssh-sub-account-setting/
https://qiita.com/aild_arch_bfmv/items/99dd58fc6be84f87a075
https://qiita.com/RyoMa_0923/items/681f86196997bea236f0
https://qiita.com/clutter/items/5e319bdf707e4e76d463
https://qiita.com/gologo13/items/7e4e404af80377b48fd5