GoogleClabローカルランタイムをWindowsPC上のWSL2Ubuntu＋Dockerで構築する方法（リモートホスト対応）

GoogleClab環境では、デフォルトで準備されているランタイムには制限（90分ルール、12時間ルール、GPU利用制限等）があるため機械学習等で連続時間処理させる場合のボトルネックとなる。これを解消するためにGPU搭載のWindowsPCをホスト機としてローカルランタイムを構成してGoogleClabで利用することができる。
　本資料では、GPU搭載のWindowsPCをホスト機として、WSL2Ubuntu上でグラフ深層学習用のPytorch+PyG（PyTorch Geometric）ベースのDockerコンテナを作成し、GoogleClab用のランタイムとして活用し、さらにそのランタイムをリモートPCからも利用する方法を紹介する。

# WindowsPC（ホスト機）の仕様

- OS:Windows 11 Home 23H2
- CPU:Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz
- メモリ:32.0 GB
- GPU:NVIDIA GeForce RTX 2080 SUPER

# 【前提条件】
- DockerはDockerDesktopForWindowsがインストールされている。（常駐起動している）
- Dockerコンテナの作成、コマンドの実行はWSL2Ubuntu上から行う。
- NVIDIAのドライバはGeForceの公式サイトからダウンロードして最新版をインストールしている。

# NVIDIA Container Toolkitのインストール
まず、WindowsPC（ホスト機）上のWSL2UbuntuでNVIDIA Container Toolkitをインストールする。

以前は、このサイト「[待ってました CUDA on WSL2](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa)」に記載のShellScriptスクリプトを使ってインストールしていましたが、nvidia-docker2が非推奨になりnvidia-container-toolkitに変更になったので、この記事「[【Ubuntu 24.04】NVIDIA Container Toolkit（nvidia-docker）のインストール方法](https://effegma.com/how-to-install-nvidia-container-toolkit/)」に記載の手順で行う。

GPGキーの取得と保存
```bash:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
```
NVIDIAのAPTリポジトリリストのダウンロードと保存
```bash:
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
```
パッケージリストの更新
```bash:
sudo apt update
```
NVIDIA Container Toolkitをインストール
```bash:
sudo apt install nvidia-container-toolkit -y
```

# Dockerを再起動
Docker(DockerDesktopForWindows)はWSL2Ubuntu上の以下のコマンドで再起動を行うか、WindowsのDockerDesktopForWindowsのアプリケーションUIから再起動を行う。

```bash:
sudo service docker restart
```

# Dcokerfileとrequirements.txtの作成
今回は、PyG（PyTorch Geometric）を使ったグラフ深層学習用のローカルランタイムを構築するために、ベースコンテナにはCuda（cuda:12.1.0）を利用して、以下のパッケージをインストールしたコンテナイメージをビルドするためのDockerfileとrequirements.txtの例を記載する。
- ベース： Cuda（cuda:12.1.0）
    - pytorch
    - python3-pip
    - python3-dev
    - curl
    - git
    - torch-scatter
    - torch-sparse
    - pytorch-geometric
    - numpy
    - matplotlib
    - scikit-learn
    - jupyter

※ベースコンテナのcudaバージョンは、利用する環境に応じたものを利用する。
(https://hub.docker.com/r/nvidia/cuda/tags)

```Dockerfile:Dockerfile
#Dockerfile for creating a Pytorch-based local runtime
#

#Base container
FROM nvidia/cuda:12.1.0-cudnn8-devel-ubuntu22.04

#Basic package install
RUN apt-get update && apt-get install -y \
    python3-pip \
    python3-dev \
    curl \
    git

#Install Pytorch manualy
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

#Working Directory Settings
WORKDIR /workspace
COPY . /workspace
#RUN mv /workspace /content
#RUN ln -s /content /workspace

#Install the packages listed in requirements.txt
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

```
```sh:requirements.txt
torch==2.3.1
torch-scatter -f https://data.pyg.org/whl/torch-1.12.0.html
torch-sparse -f https://data.pyg.org/whl/torch-1.12.0.html
git+https://github.com/pyg-team/pytorch_geometric.git
numpy
matplotlib
scikit-learn
jupyter
```

# Dcokerイメージのビルド
WSL2Ubuntu上で以下のコマンドを実行してDockerイメージをビルドする。
```bash:
docker build --no-cache -t my-pytorch-geometric-gpu .
```
ビルドしたDockerイメージの確認。
```bash:
docker image ls my-pytorch-geometric-gpu
```

# Dcokerコンテナの起動
Dockerイメージのビルドが確認できたら、以下のコマンドでDockerコンテナを起動する。
※Dockerコンテナ内のJupyter Notebookも一緒に起動する。
```bash:
docker run --gpus all -it --rm -v $(pwd):/workspace -p 8888:8888 my-pytorch-geometric-gpu jupyter notebook --ip 0.0.0.0 --no-browser --allow-root
```
# JupyterNotebookへの接続確認
上記で起動したDcokerコンテナ内のJupyter Notebookが出力したURL（http\://127.0.0.1:8888/tree?token=\<YOUR_TOKEN>）にブラウザからアクセスしてJupyter Notebookの起動を確認する。
※\<YOUR_TOKEN>のトークンは起動ごとに違うので出力表示を確認してブラウザアクセスする。
※Jupyter Notebookのトークンは起動オプション(--NotebookApp.token)で無効化したり、任意のものに設定できる。
※2025/4ごろまではブラウザ（GoogleColab）からカーネル（Jupyter）側に認証情報（credentials）を送る仕様になっていなかったが、2025/4末ぐらいに仕様変更があったために、jupyter起動時に起動オプションを付けないと接続エラーが発生するようになった。（--NotebookApp.allow_credentials=True）
（参考）
https://github.com/googlecolab/colabtools/issues/5302

トークンを「your_token」に指定する場合
```bash:
docker run --gpus all -it --rm -v $(pwd):/workspace -p 8888:8888 my-pytorch-geometric-gpu jupyter notebook --ip 0.0.0.0 --no-browser --allow-root --NotebookApp.token='your_token' --NotebookApp.allow_origin='https://colab.research.google.com' --NotebookApp.allow_remote_access=True --NotebookApp.disable_check_xsrf=True --NotebookApp.allow_credentials=True
```
トークンを無効にする場合
```bash:
docker run --gpus all -it --rm -v $(pwd):/workspace -p 8888:8888 my-pytorch-geometric-gpu jupyter notebook --ip 0.0.0.0 --no-browser --allow-root --NotebookApp.token='' --NotebookApp.allow_origin='https://colab.research.google.com' --NotebookApp.allow_remote_access=True --NotebookApp.disable_check_xsrf=True --NotebookApp.allow_credentials=True
```

# GoogleColabのローカルランタイムを設定する
　ブラウザでの確認ができたら、GoogleClabのローカルランタイムの接続先を上記のURLに指定すると、PytorchベースのDockerコンテナをローカルランタイムとして利用できるようになり、ホストPCのGPUもcudaとして利用できるようになる。

# リモートPCからGoogleClab用ローカルランタイムへの接続手順
次にGPU搭載のWindowsPC（ホスト機）で動作しているローカルランタイムへ別のリモートPCから接続する方法を記載する。

- 全体構成図
以下に全体構成図を記載する。
![Fig1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1310955/a988d0de-5e0e-aaac-f289-926528656827.jpeg) \

- WindowsPC（ホスト機）のWSL2WSL2Ubuntu上にSSHサーバをインストール
```bash:
sudo apt update
sudo apt install openssh-server
sudo service ssh start
```

　起動の確認を行う。
```bash:
service --status-all|grep ssh　
```

　/etc/ssh/sshd_configの以下の設定を確認する。
```bash:
PasswordAuthentication yes
```

　もし、設定されていなければ上記設定を行って再起動する。
```bash:
sudo service ssh restart
```

- WindowsPC（ホスト機）のポートフォワーディングを設定
Windows上（コマンドプロンプトまたはPowerShell）で以下のコマンドを実行する。

```powershell:
netsh interface portproxy add v4tov4 listenport=22 listenaddress=0.0.0.0 connectport=22 connectaddress=<WSL2_IP_ADDRESS>
```

\<WSL2_IP_ADDRESS>は、WSL2Ubuntuの以下のコマンドで確認する。
```bash:
ip addr show eth0
```

- WindowsPC（ホスト機）のWSL2WSL2Ubuntu側のファイヤーウォールの設定確認
以下のコマンドでWSL2Ubuntu側のFWの設定確認をする。（SSH（22）のポートを開ける）
```bash:
sudo ufw allow ssh
sudo ufw enable
sudo ufw status
```

- Windowsファイヤーウォールの設定
次にWindowsPC（ホスト機）のファイヤーウォールも設定してSSH（22）のポートを開ける。
    - コントロールパネルー「システムとセキュリティ」ー「Windows Defender ファイアウォール」ー「詳細設定」
    - 「受信の規則」ー「新しい規則」で新しい規則を追加
    - 「ポート」を選択し、次へをクリックします。
    - 「特定のローカルポート」に22を入力し、次へをクリックします。
    - 「接続を許可する」を選択し、次へをクリックします。
    - プロファイル（ドメイン、プライベート、パブリック）を選択し、次へをクリックします。
    - 名前[OpenSSH-Server-In-TCP]を入力して完了をクリックします。
    <br/>

- リモートPCからの接続
SSHポート転送可能なSSHクライアントとしてTeraTermがリモートPCにインストールされている場合に、リモートPC側からWindowsPC（ホスト機）のWSL2UbuntuにSSHログインしてポート転送の設定を行う方法を説明する。
TeraTermでは、以下のような手順でポート転送の設定を行う。
   
    - 「ファイル」ー「新しい接続」でusername@<ホストWindowsPCのIPアドレス>でSSHログイン接続する
    - 接続完了したら「設定」ー「SSH転送」
    - 「SSH転送設定」ダイアログが表示されたら、「追加」をクリックします。
    - 「種類」を「Local」に設定します。
    - 「送信ポート」に8888を入力します。
    - 「送信先ホスト」にlocalhostを入力します。
    - 「OK」をクリックして設定を保存します。
    <br/>

- 接続確認
  [JupyterNotebookへの接続確認](#jupyternotebookへの接続確認)と同様の接続確認を行いリモートPCのブラウザからのアクセス確認ができれば、[GoogleColabのローカルランタイムを設定する](#googlecolabのローカルランタイムを設定する)と同じ手順でリモートPCからもローカルランライム接続が可能となる。

# 参考

https://qiita.com/techstrom/items/ed9a4862490453b2a312
https://effegma.com/how-to-install-nvidia-container-toolkit/
https://webbigdata.jp/post-9729/

# 変更履歴

- 2024/10/08 一Dockerfile変更、Pytorchベース→nvidia/cudeベースに。
- 2024/11/21 一NVIDIA Container Toolkitのnvidia-docker2非推奨によりインストール手順を全面変更
- 2025/05/08 一GoogleColabとJupyterNotebookの接続仕様変更によりJupyterNotebookの起動オプションを追加変更