Podman(WSL2,podman-machine-default)とVSCodeでGPU適用したdevcontainerを利用する

当サイトではアフィリエイト広告を利用しています

WSL2上のPodman(Distroはpodman-default-machine)においてVSCodeのdevcontainerを利用したGPUコンテナの実行を行うことが出来ました。

ただ、Dockerfileを使う場合docker-compose.ymlを1つで対応することはできず、ビルド用とdevcontainer用の2つに分けて対応しました。

今回行った設定を記録しておきます。

環境

利用環境のバージョンは次のようになっています。

  • OS: Windows 10
  • GPU: Geforce GTX 1660
    • Win10にGPUドライバはインストール済み
  • Podman: 4.6.0
  • WSL2 Distro: podman-machine-default (Fedora37)
  • VSCode: 1.81.0

今回のPCへのWSL2,PodmanやGPUコンテナ利用ためのnvidia-container-tooolkitの導入手順は以下の記事でまとめています。

Jupyterでの補完問題

VSCodeだとJupyter拡張でpodman runしたJupyterコンテナに接続はできるのですが補完が出来ないです。

Devcontainerなら補完できるとのことで、Podman+GPUで既存のdocker-composeで設定を試みましたが、大分難航しました。

Microsoft公式提供のdevcontainerのテスト

とりあえずdevcontainer公式のPython(mcr.microsoft.com/devcontainers/python)で実行してみましたが、Podmanだとrootlessの関係で起動できませんでした。

root周りのエラーがあったのでこちらのHPを参考にdevcontainers.jsonに設定を追記しました。。

 "runArgs": [
  "--userns=keep-id:uid=1000,gid=1000"
 ],
 "containerUser": "vscode",
 "updateRemoteUserUID": true,
 "containerEnv": {
   "HOME": "/home/vscode"
 }

これで実行することができました。この設定をベースに自分で用意したImageでdevcontainerの実行をしていきます。

docker-compose.ymlでDockerfileを使った時のエラー

devcontainer提供のimageだと外部のdocker-compose.yml使ってもすんなり起動してますが、devcontainer以外のImage使ったdocker-composeを利用すると次のようなエラーが出てしまいます。

Error: ENOENT: no such file or directory, open 'c:\Users\username\.vscode\extensions\ms-vscode-remote.remote-containers-0.299.0\Dockerfile'

devcontainers.jsonでdocker-compose.ymlではなくてDockerfileを直接指定する場合はubuntuイメージの起動が出来まして、docker-compose.ymlを指定する場合であってもDockerfileではなくてimageを直接指定する場合は起動が出来ました。

どうもdocker-compose.ymlで指定するDockerfileのパスの問題みたいです。ということでdevcontainer.jsonと同じディレクトリにDockerfile設置したりしてみましたが、どうも上手くいかなかったです。

独自のDockerfileを使ってdevcontainer機能時の設定

以下のようにdocker-compose.ymlを分ければ上手くいきました。1つのdocker-compose.ymlで機能できれば良かったのですが、今回は諦めます。

2つdocker-compose.ymlで片方はdevcontainerを使わない普通のdocker-compose.ymlでbuildとiamgeの設定を行い、もう片方はbuild指定をせずにimage指定のみを行っています。

ディレクトリ構造

以下のようなディレクトリ構造になっており、コンテナ起動時はworkspaceをマウントしてipynbを記述していきます。

│  docker-compose.yml
│  Dockerfile
├─.devcontainer
│      devcontainer.json
│      docker-compose.yml
└─workspace
    │  notebook.ipynb
    └─.ipynb_checkpoints

Dockerfile

GPUが有効でtensorflowを使えるjupyter notebook用のImageを次のように設定しています。

FROM nvcr.io/nvidia/tensorflow:23.07-tf2-py3

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

RUN groupadd --gid $USER_GID $USERNAME \
    && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME

RUN pip install -U pip &&\
    pip install --no-cache-dir matplotlib

WORKDIR /home/$USERNAME
USER $USERNAME

docker-compose.yml

以下がpodman-compose用のdocker-compose.ymlです。こちらはImageのbuildとdevcontainerを使わないコンテナ起動に利用します。

userns_mode: keep-idはマウントするボリュームがrootになってしまうのを防いでvscodeユーザー扱いでマウント出来ます。jsonと引数が違うので混乱しました。

version: '3'
services:
  jupyter:
    build:
      context: ./
      dockerfile: Dockerfile
    image: nvidia-tf-homl
    ports:
    - "8888:8888"
    volumes:
    - ./workspace:/home/vscode/workspace
    devices:
    - "nvidia.com/gpu=all"
    user: vscode
    userns_mode: keep-id
    command: jupyter lab --notebook-dir=/home/vscode/workspace --NotebookApp.token="" --NotebookApp.custom_display_url="http://localhost:8888"

.devcontainer/devcontainer.json

こちらはdevcontainer用の設定jsonファイルです。コンテナ内部のVSCode用の設定の他、--userns=keep-idでマウントするボリュームがrootになってしまうのを防いでvscodeユーザー扱いでマウント出来ます。

{
  "name": "nvidia-tf-homl-vscode",
  "dockerComposeFile": ["./docker-compose.yml"],
  "service": "jupyter",
  "shutdownAction": "none",
  "workspaceFolder": "/home/vscode/workspace",
  "runArgs": ["--userns=keep-id"],
  "containerEnv": {
    "HOME": "/home/vscode"
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.black-formatter",
        "ms-toolsai.jupyter",
        "ms-python.python",
        "ms-python.vscode-pylance"
      ],
      "settings": {
        "editor.defaultFormatter": "ms-python.black-formatter"
      }
    }
  }
}

.devcontainer/docker-compose.yml

こちらはdevcontainer用のdocker-compose.ymlです。devcontaierで自動で利用されるファイルです。

こちらではビルドは行わず、imageの指定のみを行う形にしています。

version: '3'
services:
  jupyter:
    image: nvidia-tf-homl
    ports:
    - "8888:8888"
    volumes:
    - ../workspace:/home/vscode/workspace
    devices:
    - "nvidia.com/gpu=all"
    user: vscode
    userns_mode: keep-id
    command: /bin/sh -c "while sleep 1000; do :; done"

まとめ

  • WSL2/GPU/Podman/Vscode/devcontainerで独自Dockerfileを使う設定を調査
  • docker-compose.ymlを通常ビルド用とdevcontainer用の2つに分けて解決
  • Podmanのrootless対応のためにkeep-id設定も必要