MacからUbuntu20.04に接続してリモート開発 (VScode + Docker+ Poetry + PyTorch+GPU)
やりたいこと
- Mac環境を汚したくない
- Ubuntuにリモートアクセスで開発
- Dockerのコンテナ分離とPoetryの依存関係管理で誰でも同じ環境で開発できるようにしたい
- UbuntuのGPUを簡単に使う(cudaとかで振り回されたくない)
ゴール
MacからUbuntuに接続して、MacのVScodeからUbuntuのPyTorch(GPU)を使えるようにする
スタート
- Mac:下記環境
- Ubuntu:クリーンインストールから
*Macでのコマンドは%
、Ubuntuでのコマンドは$
で記載してます。MacからSSH接続した先のUbuntuでコマンドを打つ時は$
で記載しています。
環境
Mac
- Macbook Pro 2020 Intelチップ
- Big Sur 11.5.2
- Docker v20.10.7
- VScode v1.61.0 (Remote developmentのextentionは入っている前提)
Ubuntu
- Ubuntu 20.04
- RTX3090
Ubuntuでの処理
ざっくりとした手順は以下の通り。
- クリーンインストール
- 必要なアプリのインストール
- NVIDIAドライバ(CUDA経由)のインストール
- Dockerのインストール
- NVIDIA Containerのインストール
- Python環境の設定
クリーンインストール
下記のUbuntu 20.04.3 LTS (Focal Fossa)をインストール。インストール方法はUSB挿してbootするだけなので割愛
結局リモート接続するのでキーボートレイアウトはどうでもよかったが、PC付属が日本語キーボードなのでキーレイアウトは日本語で設定
*USキーボード配列で日本語入力したい人は以下が簡単でおすすめ
最低限のアプリケーションインストール
日本語化入力をできるようにする
$ sudo apt install ibus-mozc
$ ibus restart
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'jp'), ('ibus', 'mozc-jp')]"
参考
最低限必要なアプリをインストール
- Chrome
- VScode
CUDAのインストール
ubuntu-drivers devices
→ubuntu-drivers autoinstall
でNVIDIAのドライバーを入れる必要はなく、CUDAのインストール手順で入れるのが推奨らしいので従う。
2021/12/2現在の最新PyTorch使うので11.3.0でいく。後述のNVIDIA Containerも11.3.0-cudnn8を使うのでここは念のため合わせとく。
(cuda11.5でもNVIDIA Container使えばPyTorchが動くの確認したけど、本当に動作確認しかしていない)
最後のコマンドだけ公式と違ってsudo apt-get -y install cuda-drivers
なので注意。
$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
$ sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ wget https://developer.download.nvidia.com/compute/cuda/11.3.0/local_installers/cuda-repo-ubuntu2004-11-3-local_11.3.0-465.19.01-1_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu2004-11-3-local_11.3.0-465.19.01-1_amd64.deb
$ sudo apt-key add /var/cuda-repo-ubuntu2004-11-3-local/7fa2af80.pub
$ sudo apt-get update
$ sudo apt-get -y install cuda-drivers
参考
インストール中に謎の画面出てくるのでctr+下カーソルで出てくる画面でパスワード入れる。
この画面見たことないからマザーボード依存なのか不明。
PCを再起動すると画像のような画面が出てくるので、Perform MOK manegementからEnroll MOKを選択。
確かcontinueで次に進む(写真撮り忘れた)
さっき設定したパスワードを入力してreboot
この手順でnvidia-smiが使えるようになる。これやらないとNVIDIA Driverと通信できないと怒られる。
Dockerのインストール
$ sudo apt-get update
$ sudo apt-get install \
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
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
動作確認
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:cc15c5b292d8525effc0f89cb299f1804f3a725c8d05e158653a563f15e4f685
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Hello From Dockerが確認できればOK。
(動作確認できたら自動でこのイメージ削除してほしい)
dockerのsudoなくす設定して再起動。
$ sudo usermod -aG docker $USER
NVIDIA-Containerのインストール まずはdockerの起動設定
$ curl https://get.docker.com | sh \
&& sudo systemctl --now enable docker
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
テスト。HPのテストコード通りpullするイメージがcuda11.0でも問題なく動作する
$ sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
Unable to find image 'nvidia/cuda:11.0-base' locally
11.0-base: Pulling from nvidia/cuda
54ee1f796a1e: Pull complete
f7bfea53ad12: Pull complete
46d371e02073: Pull complete
b66c17bbf772: Pull complete
3642f1a6dfb3: Pull complete
e5ce55b8b4b9: Pull complete
155bc0332b0a: Pull complete
Digest: sha256:774ca3d612de15213102c2dbbba55df44dc5cf9870ca2be6c6e9c627fa63d67a
Status: Downloaded newer image for nvidia/cuda:11.0-base
Thu Dec 2 04:10:06 2021
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 465.19.01 Driver Version: 465.19.01 CUDA Version: 11.3 |
|-------------------------------+----------------------+----------------------+
| 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 NVIDIA GeForce ... On | 00000000:01:00.0 On | N/A |
| 0% 36C P8 19W / 350W | 284MiB / 24259MiB | 3% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
Python設定
Ubuntu20.04はデフォルトでpython=python3になっていないので設定しとく
何もせずにpythonコマンドうつと以下のようになる
$ python
Command 'python' not found, did you mean:
command 'python3' from deb python3
command 'python' from deb python-is-python3
これらを入れて対処
$ sudo apt-get install python-is-python3
$ sudo apt-get install python3-distutils
Poetry
どうせDockerコンテナ内で作業するのでいらない人は飛ばして良い
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
Templateをclone
ここからの作業はMacでSSH接続設定をして、SSH接続してからもちろんでもできる。
事前に作っておいたtemplateをclone。公開設定しているので自由に使っていただいてOKですが、とりあえず感半端ないので適宜修正してください(ごめんなさい)
$ git clone https://github.com/SO-ES1/pytorch-template.git
クリーンインストール後でGit設定をしていない場合、gitのパスワードはGithubのsettingsからpersonal access tokenを作成してそれを入れること。
VSCodeでContainerにもぐる
とりあえず拡張機能を入れる。
- Python(ms-python.python)
- Remote Development(ms-vscode-remote.vscode-remote-extensionpack)
- Docker(ms-azuretools.vscode-docker)
さっきcloneしたフォルダをVScodeで開く。
MacからのリモートSSH接続を考えなければ単純にRemoteContainerでプロジェクトフォルダを開きなおせばいいが、RemoteSSH+RemoteContainerを実現するためにはイメージのビルドとコンテナの初回起動が必要。(これ以外のやり方がわからない・・・)
DockerfileをもとにImage作成。
$ docker build -t template ./
この状態だと以下のようにコンテナが表示されないのでコマンドで起動する
$ docker run -it --gpus all -v /<YOUR DIR>/pytorch-master/:/app/ template
この時点でコンテナ内でnvidia-smiが叩けるようになる
root@2d5e4929239c:/app# nvidia-smi
Thu Dec 2 05:03:10 2021
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 465.19.01 Driver Version: 465.19.01 CUDA Version: 11.3 |
|-------------------------------+----------------------+----------------------+
| 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 NVIDIA GeForce ... On | 00000000:01:00.0 On | N/A |
| 0% 40C P8 17W / 350W | 337MiB / 24259MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
コンテナ内でPyTorch含むライブラリのインストール
一旦コンテナから抜ける
root@2d5e4929239c:/app# exit
exit
この時点でさっきはなかったコンテナがVScodeに表示されるので、□に+みたいなやつでAttachする
ついでに邪魔なhello dockerは削除した
コンテナ内に入れると左下がこんな感じに変わる
Pythonの拡張機能を入れ直す
open folderから/app/を選択(自分でここをworkdirに設定したため)
環境をpoetryでインストール。virtual環境にする必要はないが個人的にはしたほうが分離感が出て好きなので設定している(すでにdockerで分離されているが・・・)
このPoetryの中身は好きに変えていい。私適当に入れたライブラリがGitには登録されている。
ちなみにPyTorchのversion指定インストールをPoetryから入れたい時は以下のようにする。この情報知りたかった人結構いるんじゃないかなと密かに思っている・・・
poetry add "https://download.pytorch.org/whl/cu113/torch-1.10.0%2Bcu113-cp38-cp38-linux_x86_64.whl"
使えるwhlはここで参照できる。
追記
このやりかただとtorchvisionやtorchaudioを入れることができない。
pip3 install torch==1.10.0+cu113 torchvision==0.11.1+cu113 torchaudio==0.10.0+cu113 -f https://download.pytorch.org/whl/cu113/torch_stable.html
を追加してやむなく入れた・・・ 結局Poetry管理外・・・
$ poetry install
output
poetry install
Skipping virtualenv creation, as specified in config file.
Updating dependencies
Resolving dependencies... (141.8s)
Writing lock file
Package operations: 128 installs, 0 updates, 0 removals
• Installing zipp (3.6.0)
• Installing attrs (21.2.0)
• Installing importlib-resources (5.4.0)
• Installing pyrsistent (0.18.0)
• Installing six (1.16.0)
• Installing traitlets (5.1.1)
• Installing entrypoints (0.3)
• Installing ipython-genutils (0.2.0)
• Installing jsonschema (4.2.1)
• Installing jupyter-core (4.9.1)
• Installing nest-asyncio (1.5.4)
• Installing parso (0.8.3)
• Installing ptyprocess (0.7.0)
• Installing pyparsing (3.0.6)
• Installing python-dateutil (2.8.2)
• Installing pyzmq (22.3.0)
• Installing tornado (6.1)
• Installing wcwidth (0.2.5)
• Installing backcall (0.2.0)
• Installing decorator (5.1.0)
• Installing jedi (0.18.1)
• Installing jupyter-client (7.1.0)
• Installing markupsafe (2.0.1)
• Installing matplotlib-inline (0.1.3)
• Installing nbformat (5.1.3)
• Installing packaging (21.3)
• Installing pexpect (4.8.0)
• Installing pickleshare (0.7.5)
• Installing prompt-toolkit (3.0.23)
• Installing pycparser (2.21)
• Installing pygments (2.10.0)
• Installing webencodings (0.5.1)
• Installing bleach (4.1.0)
• Installing cffi (1.15.0)
• Installing debugpy (1.5.1)
• Installing defusedxml (0.7.1)
• Installing ipython (7.30.0)
• Installing jinja2 (3.0.3)
• Installing jupyterlab-pygments (0.1.2)
• Installing mistune (0.8.4)
• Installing nbclient (0.5.9)
• Installing pandocfilters (1.5.0)
• Installing testpath (0.5.0)
• Installing argon2-cffi (21.1.0)
• Installing certifi (2021.10.8)
• Installing charset-normalizer (2.0.8)
• Installing idna (3.3)
• Installing ipykernel (6.6.0)
• Installing nbconvert (6.3.0)
• Installing prometheus-client (0.12.0)
• Installing pyasn1 (0.4.8)
• Installing send2trash (1.8.0)
• Installing terminado (0.12.1)
• Installing urllib3 (1.26.7)
• Installing cachetools (4.2.4)
• Installing click (8.0.3)
• Installing greenlet (1.1.2)
• Installing itsdangerous (2.0.1)
• Installing notebook (6.4.6)
• Installing oauthlib (3.1.1)
• Installing pyasn1-modules (0.2.8)
• Installing requests (2.26.0)
• Installing rsa (4.8)
• Installing smmap (5.0.0)
• Installing werkzeug (2.0.2)
• Installing flask (2.0.2)
• Installing gitdb (4.0.9)
• Installing google-auth (2.3.3)
• Installing importlib-metadata (4.8.2)
• Installing jupyterlab-widgets (1.0.2)
• Installing mako (1.1.6)
• Installing numpy (1.21.4)
• Installing python-editor (1.0.4)
• Installing pytz (2021.3)
• Installing qtpy (1.11.2)
• Installing requests-oauthlib (1.3.0)
• Installing sqlalchemy (1.4.27)
• Installing tabulate (0.8.9)
• Installing tomli (1.2.2)
• Installing typing-extensions (4.0.1)
• Installing websocket-client (1.2.1)
• Installing widgetsnbextension (3.5.2)
• Installing absl-py (1.0.0)
• Installing alembic (1.4.1): Installing...
• Installing alembic (1.4.1)
• Installing cloudpickle (2.0.0)
• Installing cycler (0.11.0)
• Installing databricks-cli (0.16.2)
• Installing docker (5.0.3)
• Installing fonttools (4.28.2)
• Installing gitpython (3.1.24)
• Installing google-auth-oauthlib (0.4.6)
• Installing grpcio (1.42.0)
• Installing gunicorn (20.1.0)
• Installing iniconfig (1.1.1)
• Installing ipywidgets (7.6.5)
• Installing joblib (1.1.0)
• Installing jupyter-console (6.4.0)
• Installing kiwisolver (1.3.2)
• Installing markdown (3.3.6)
• Installing mypy-extensions (0.4.3)
• Installing pandas (1.3.4)
• Installing pathspec (0.9.0)
• Installing pluggy (1.0.0)
• Installing protobuf (3.19.1)
• Installing platformdirs (2.4.0)
• Installing prometheus-flask-exporter (0.18.6)
• Installing pillow (8.4.0)
• Installing py (1.11.0)
• Installing pyyaml (6.0)
• Installing qtconsole (5.2.1)
• Installing querystring-parser (1.2.4)
• Installing regex (2021.11.10)
• Installing scipy (1.7.3)
• Installing setuptools-scm (6.3.2)
• Installing sqlparse (0.4.2)
• Installing tensorboard-data-server (0.6.1)
• Installing tensorboard-plugin-wit (1.8.0)
• Installing threadpoolctl (3.0.0)
• Installing toml (0.10.2)
• Installing black (21.11b1)
• Installing jupyter (1.0.0)
• Installing matplotlib (3.5.0)
• Installing mlflow (1.22.0)
• Installing opencv-python (4.5.4.60)
• Installing pytest (6.2.5)
• Installing scikit-learn (1.0.1)
• Installing tensorboard (2.7.0)
• Installing torch (1.10.0+cu113 https://download.pytorch.org/whl/cu113/torch-1.10.0%2Bcu113-cp38-cp38-linux_x86_64.whl)
これでPyTorchがGPUを認識する。cuDNNも登録作業なしに使えるようになる。
root@2d5e4929239c:/app# poetry shell
Skipping virtualenv creation, as specified in config file.
Virtual environment already activated: /usr
root@2d5e4929239c:/app# python
Python 3.8.10 (default, Sep 28 2021, 16:10:42)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> print(torch.cuda.is_available())
True
>>> print(torch.cuda.get_device_capability())
(8, 6)
>>> torch.backends.cudnn.version()
8200
MacからSSH接続できるように設定
UbuntuのifconfigでIPアドレスを確認。確認できればどんなやり方でも良い
$ sudo apt-get install net-tools
$ ifconfig
ここを参考に実施
Open SSH serverのインストール
$ sudo apt-get update
$ sudo apt-get install openssh-server
以下コマンドでSSHができるか確認
$ sudo systemctl status ssh
Portをセキュリティのために変更
sudo nano /etc/ssh/sshd_config
ここのPortの#を消してデフォルトの22を49152から65535のどれかに変更
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
再起動
Macでの作業
やっとMacに帰ってきた。
なにはともあれssh鍵を生成する。別にデフォルトでもいいが、試しにというのもありより強そう(?)なed25519で生成した。
% ssh-keygen -t ed25519
公開鍵をubuntuに渡す
% scp -P 設定したポート番号 ~/.ssh/id_ed25519.pub Ubuntuのログイン名@XXX.XXX.XXX.XXX:~/id_ed25519.pub
fingerprintがなんとやらと聞かれるがyesで回答して、ubuntuのログインパスワード入れればOK
複数のPCからアクセスしたいときは公開鍵の名前を適当に変更して保存しておけば良い
Ubuntuでの作業
Macに帰ってきたと思ったらまたUbuntuで少し設定。
公開鍵をauthorized_keysとして登録。
$ mkdir ~/.ssh
$ hmod 700 ~/.ssh
$ cat ~/id_ed25519.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
デフォルトだと公開鍵なくてもログインパスワードあればログインできるらしいので修正
$ sudo nano /etc/ssh/sshd_config
PasswordAuthenticationのコメントアウトを消してnoに変更
(本当に必要なのかな・・・)
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no
sudo service sshd restart
念の為PCごと再起動もしとく
Macでの作業
またMacに帰ってきてVScodeのRemote SSHで接続するための手順を実施
SSH接続のためのconfigを作成。
% nano ~/.ssh/config
以下のような感じで作成する。
HostNameはIPアドレス、
Userはログイン名(自分しか使わないならubuntuをインストールした時に設定した名前でOK)、
IdentitiFileはssh鍵が保存されているところ、
PortはUbutnuで設定したポートを指定
Host Ubuntu
HostName XXX.XXX.XXX.XXX
User YYYYY
IdentityFile ~/.ssh/id_ed25519
Port XXXXX
アクセス権付与
% touch ~/.ssh/config
% chmod 600 ~/.ssh/config
これをつくるとVSCodeのRemoteSSHのSSH TARGETに出現する
targetの横にある□+でssh接続ができる
VScode上でterminalを開けばUbuntuでのTerminalが使えている状態になる。
コンテナにアタッチ
Ubuntuでremote containerに入ることはできたので、それをMacからの操作で行う
リモートエクスプローラーをSSH TargetsからCountainersに切り替えてさっき作ったコンテナに□+からアタッチする
無事MacからUbuntuにアクセスしてUbuntu内のリモートコンテナに潜ることができました。
もちろんこのVSCodeで作成したコードのビルドはUbuntuのGPUで実行されます。
まとめ
VSCode神
補足 MacでPoetryのインストール方法とPoetry初期化
Ubuntuで全部完結するのでMacを汚す必要はないが、以下の方法でできる。
- Poetryのインストール
homebrew経由で実施するのでbrewが入っていない場合は、以下から実施
https://brew.sh/index_ja
% brew install poetry
- 適当にプロジェクトのフォルダ作成
TODO: ここにディレクトリ構造書く - Poetryでプロジェクトの初期化
% poetry init
今回はpython3.8の追加パッケージなしで一旦プロジェクト作成しました(名前は隠してます)
% poetry init
This command will guide you through creating your pyproject.toml config.
Package name [template_master]:
Version [0.1.0]:
Description []:
Author [XXX, n to skip]:
License []: MIT
Compatible Python versions [^3.7]: ^3.8
Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] no
Generated file
[tool.poetry]
name = "template_master"
version = "0.1.0"
description = ""
authors = ""
license = "MIT"
[tool.poetry.dependencies]
python = "^3.8"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Do you confirm generation? (yes/no) [yes]
これでpoetry.tomlが以下のようにできます
[tool.poetry]
name = "template_master"
version = "0.1.0"
description = ""
authors = ""
license = "MIT"
[tool.poetry.dependencies]
python = "^3.8"
[tool.poetry.dev-dependencies]
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
- Poetryが作成する環境の場所設定
% poetry config virtualenvs.in-project true --local
あとでDockerコンテナ内で作業することになるので仮想環境を作る必要はぶっちゃけないのですが、誤爆したくないので仮想環境を作ります。
これによってpyproject.tomlができあがります。
- 必要な依存関係をインストール
ここまでこればあとはPoetry addコマンドで入れたいものを入れていくだけです。
Discussion