Dockerを使ったWindows上の実験環境構築
TL;DR
イメージからgpuコンテナをビルドして起動
docker image build -t <container name> .
docker run --name <container name> --gpus all --shm-size 8gb -v <e.g. /C/project/dir>:/workspace -i -t <image name>
これまではVSCodeのDockerとReopen Containerでbuild imageからrunまで全部を扱っていたのですが、エラーでコンテナにアクセスできない事件が起こると解決が難しいため、素でDockerを使えるように覚書を残すことにしました。
よくこういうエラーに出くわす
Command failed:
C:\Users\USER\AppData\Local\Programs\Microsoft VS Code\Code.exe
--ms-enable-electron-run-as-node c:\Users\USER\.vscode\extensions\ms-vscode-remote.remote-containers-0.309.0\dist\spec-node\devContainersSpecCLI.js up
--user-data-folder c:\Users\USER\AppData\Roaming\Code\User\globalStorage\ms-vscode-remote.remote-containers\data
--container-session-data-folder /tmp/devcontainers-32d3095e-6f39-41e8-a350-ccb11b3f17631695564713488
--workspace-folder e:\EXPERIMENT\project_1
--workspace-mount-consistency cached
--id-label devcontainer.local_folder=e:\EXPERIMENT\project_1
--id-label devcontainer.config_file=e:\EXPERIMENT\project_1\.devcontainer\devcontainer.json
--log-level debug
--log-format json
--config e:\EXPERIMENT\project_1\.devcontainer\devcontainer.json
--default-user-env-probe loginInteractiveShell
--mount type=volume, source=vscode, target=/vscode, external=true
--skip-post-create
--update-remote-user-uid-default on
--mount-workspace-git-root true
他にもGPUとメモリのアクセスなどでRemote Explorerがアクセスできないことがある。
これが起こるともうどうしようもない。
Dockerfile用意
実験はE:\EXPERIMENT\project_1\
の上で行う。全体の流れとしては、まずDocker上のコンテナを作り、GPUアクセスが可能な状態にしてコンテナへログインする。たったこれだけなのだが、Dockerへの謎の忌避感があるため、精神的に重労働である。なぜ...?
まずDockerfileを書く。最小構成は次のようなimageを使うことが多い。
ARG PYTORCH="2.1.1"
ARG CUDA="12.1"
ARG CUDNN="8"
FROM pytorch/pytorch:${PYTORCH}-cuda${CUDA}-cudnn${CUDNN}-devel
ENV TORCH_CUDA_ARCH_LIST="6.0 6.1 7.0 7.5 8.0 8.6+PTX" \
TORCH_NVCC_FLAGS="-Xfatbin -compress-all" \
CMAKE_PREFIX_PATH="$(dirname $(which conda))/../" \
FORCE_CUDA="1" \
DEBIAN_FRONTEND=noninteractive
# Install the required packages
RUN apt-get update
RUN apt-get install -y ffmpeg git graphviz \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# torch torchvision
RUN pip install ipython jupyter ruff graphviz \
&& pip install numpy scikit-learn scikit-image pillow pandas polars matplotlib seaborn openpyxl \
&& pip install torchinfo torchmetrics torchview lightning timm transformers pymc
CMD ["/bin/bash"]
Containerの作成・実行・停止
箇条書きで行いたい操作をノートしていく。
imageをビルド
E:\EXPERIMENT\project_1 $ ls
dockerfile
dataset/
code.py
# path上にあるDockerfileをビルドしてimageを作成
# docker image build [オプション] PATH
# option: `--tag` (`-t`) ... 'name:tag' により名前とタグを指定
E:\EXPERIMENT\project_1 $ docker image build -t experiment:v1 .
# imageを確認
E:\EXPERIMENT\project_1 $ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
experiment v1 762dce37c70c now 13.2GB
containerを作成して実行
docker run
で作成と実行を同時に行う。作成だけのときはdocker create
を使う。
# 新たなコンテナー内でコマンドを実行
# docker run [オプション] IMAGE [COMMAND] [ARG...]
# option: `--gpu` ... コンテナに追加する GPU デバイスを指定(API 1.40 以上で対応)
# option: `--shm-size` ... /dev/shm (Dockerに占有を許可するメモリ?)のサイズを指定
# option: `-v` (`--volume`) ... ボリュームをバインドマウントする
# option: `-i` (`--interactive`) ... コンテナにアタッチしていない状態でも標準出力を開放し続ける
# option: `-t` (`--tty`) ... 疑似TTY(標準出力先のターミナル)を割り当てる
E:\EXPERIMENT\project_1 $ docker run \
--name phi_brain
--gpus all \
--shm-size 8gb \
-v /E/EXPERIMENT/project_1:/workspace \
-i \
-t \
experiment:v1
# コンテナが作成された後自動的に実行されてログイン状態になる
# E:\EXPERIMENT\project_1直下の内容が/workspace内へバインドマウントされている
root@3c81667e09f0:/workspace $ ls
dockerfile
dataset/
code.py
この-v
が曲者で、"<コンテナへ継げたいホストのディレクトリ>:<コンテナ内でマウント先を展開したいディレクトリ>"の形式でabsolute pathを渡さなければ行けないのだが、Windowsの特徴により最初ここでつまずいていた。
Windows側での素の表記はE:\EXPERIMENT\project_1\
なのだが、Dockerへ渡す場合は/E/EXPERIMENT/project_1
のようにUNIX的な表記にする必要がある。区切り文字などはMS-DOS時代の名残だと思うが、この仕様を考えた人は外出の度にちょっと長めの赤信号に掛かる呪いにかかってほしい。
containerから退出
# コンテナを起動したまま退出し、もとのターミナルの標準出力へ戻る
root@3c81667e09f0:/workspace $ # (ここで CTRL + P + Q)
# コンテナの確認
E:\EXPERIMENT\project_1 $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3c81667e09f0 experiment:v1 "/opt/nvid…" 1 hours ago Up 1 hours phi_brain
または
# コンテナを停止
root@3c81667e09f0:/workspace $ # exit
E:\EXPERIMENT\project_1 $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
containerへ再接続
# 再接続する
# docker attach [オプション] コンテナID
E:\EXPERIMENT\project_1 $ docker attach 3c81667e09f0
root@3c81667e09f0:/workspace $
これでいつでも実験を再開できる。
またはコンテナが停止している場合は次のように起動する。
E:\EXPERIMENT\project_1 $ docker start 3c81667e09f0
E:\EXPERIMENT\project_1 $ docker attach 3c81667e09f0
root@3c81667e09f0:/workspace $
DockerへVSCodeを接続
環境自体はこれで整うためCLIから全ての操作が可能なのだが、GUI上での操作に慣れた軟弱者なので標準入出力だけでは不便である。
VSCodeのDockerプラグインとRemote Explorerで快適な実験ライフを送ろう。
ms-azuretools.vscode-docker 1.26.1 Microsoft
ms-vscode.remote-explorer 0.4.1 Microsoft
インストールしたら、左のタブからDockerのアイコンを開き、接続するコンテナを選択する。
新しいwindowが開き、プロジェクトが開かれる。
これによりVSCodeのReopen Containerでエラー地獄になっても実験が滞りません。やったね。
おまけ: Dcoker Engineの保存場所変更
実験に使っているとDockerエンジンが肥大化しがちなので、OSが格納されているストレージから隔離して何が起こっても大丈夫にしておくと安心になる。
内容は https://e-penguiner.com/change-location-of-docker-on-windows/ の通りなので割愛するが、実行することだけをを端的にまとめると次になる。
# C:\Users\USER\AppData\Local\Docker\wsl\distro\ext4.vhdx ← docker engine
# C:\Users\USER\AppData\Local\Docker\wsl\data\ext4.vhdx ← docker image & container
# move ↑ to E:\DOCKER\wsl...
# export to new dir
$ wsl --export docker-desktop "E:\DOCKER\wsl\data\docker-desktop.tar"
$ wsl --export docker-desktop-data "E:\DOCKER\wsl\distro\docker-desktop-data.tar"
# delete old setting
$ wsl --unregister docker-desktop
$ wsl --unregister docker-desktop-data
# install distribution to <InstallLocation> from <InstallTarFile> as version 2
$ wsl --import docker-desktop "E:\DOCKER\wsl\data" "E:\DOCKER\wsl\data\docker-desktop.tar"
$ wsl --import docker-desktop-data "E:\DOCKER\wsl\distro" "E:\DOCKER\wsl\distro\docker-desktop-data.tar"
Discussion