比較的に安全で軽量な仮想環境を作り、それをほかの開発者とも共有できるDocker
Windows+Docker+VScode+PythonでネイティブGPUを使用可能な環境を構築することを目標にいろいろとやってみました。
Gitもインストールしています。
それぞれのStepを踏んでいますが、理解できている人は必須ではないと思います。
GPU環境だけサクッとほしい人はStep4からやればOKです。
devcontainer.jsonへの接続の仕方はStep3に書いているので、Step4,5で準備をしてからStep3の手順に従えば環境が作れると思います。
Step1.VScodeでpythonを実行する
こちらを参考に。VScodeもPythonもインストール済なのでここはサクサク行きます
すでに環境変数にPythonインタープリターへのPathが通っている状態だったので、ハローワールドはスムーズです。
Step2.DockerでPythonのコンテナを作ってみる
docker pull python:3.10-slim
docker container run -it --rm python:3.10-slim /bin/bash
これでPython3.10のイメージをインストールして、コンテナが起動し、コンテナ内にBashを通して入っている状態になります。
なお、コンテナにはルート権限で入っています。
この状態(コンテナが起動している状態)でVScodeのRemote Development(Dev Containers?)という拡張機能をインストールの上でを使って右下の><
をクリック、Attach to Running Contaier
によってVScodeからPythonコンテナに接続することができます。開発も可能です。
なおルート権限なのでホームディレクトリはrootフォルダ直下となります。
またBashやVScodeのターミナルからpipを用いてnumpyなどのライブラリをインストールでき、実行できました。
ただこの状態では以下の点で不便です。
- ファイルの保存ができない
- コンテナ起動のたびにpipでのインストールが必要
- Pylanceがインストールしたライブラリを参照できず、インテリセンスが使えず警告が消えない
- インストールしてから再接続したらインテリセンス、警告は解決しました。どゆこと…?
- Pylanceは起動時にしか参照先を更新しないんですかねぇ…?
sys.executalb #実行中のPythonインタプリタのパスを取得
pip show パッケージ名 #ライブラリのインストール先の表示
sys.path #python #ライブラリを検索するフォルダを取得
で見てみてもちゃんとDocker内を見てるんですよね…
Step3.Dockerfileなどを活用する
Dockerfile, docker-compose, devcontainer.json
を活用していきます。
Dockerfileを利用する
#ベースイメージはPython3.13の最小構成で
FROM python:3.13-slim
#/workspaceというフォルダを作業ディレクトリにする
WORKDIR /workspace
#requirements.txtをコンテナ内にコピーする
COPY requirements.txt ./
# pipのアップデート
RUN pip install --upgrade pip
# pythonパッケージをインストール
RUN pip install --no-cache-dir -r requirements.txt
# コンテナ起動時に実行するコマンドを指定
CMD ["/bin/bash"]
インストールするライブラリを以下に記載
numpy
docker run -it --rm --name コンテナ名 イメージ名
これらから必要なライブラリがインストールされたイメージを作成することができるので、ここにアクセスすることで都度手動でインストールする手間は省けます。
ただコンテナを再起動するたびにVScodeのPython拡張機能の再インストールが必要となります。
docker-compose.ymlを作成する
services: # サービスを定義しますという決まり文句
python: # pythonという名前でサービスを定義
image: python:313 # イメージのREPOSITORY名:TAG名を指定
build: . # Dockerfileを相対パスで指定
container_name: python-313 # 作成されるコンテナ名を指定
working_dir: /workspace/src # 作業ディレクトリを指定 (←コンテナ内の作業ディレクトリ
volumes: # マウントするファイルを指定する
- ./:/workspace/src # ローカルのカレントディレクトリをコンテナのworkspace/srcにマウント
tty: true # コンテナを起動し続ける
KiYuRoさんの記事からほぼコピペさせていただきました。
docker compose up -d
コマンドでコンテナを起動できます。なお、最初からインストールするライブラリを増やした場合などは、このymlから作ったイメージを消して再度イメージを作成しないと反映されないようなので注意が必要です。一応docker compose
からはライブラリを追加したimageが作成できましたが、Dockerfileからの再作成にかかる時間との兼ね合いで悩むところですね…
devcontainer.jsonも用いて、都度インストールする手間を省く
{
"name": "Python VScode", // VScodeがコンテナに接続したときのタイトルを自由に設定
"dockerComposeFile": "docker-compose.yml", // docker-conpose.ymlファイルを指定
"service": "python", // docker-conpose.ymlファイル内に記載したサービス名を指定
"workspaceFolder": "/workspace/src", // VScode接続時に開くフォルダを指定
"customizations": {
"vscode": {
"extensions": [ // コンテナ作成時にインストールする拡張機能を記載
"ms-python.python", // python拡張機能
"ms-python.debugpy", // pythonのデバッガ
"ms-python.vscode-pylance", // pythonのインテリセンス
],
"settings": { // VScodeの設定を記載
"files.autoSave": "afterDelay" // ファイルのオートセーブ
}
}
}
}
customization
のvscode-extension
は拡張機能のIDを貼り付けます。
vscode-settings
は表示>コマンドパレットからopen user settings(JSON)
で開けるファイルに中身が一覧で表示されるので必要なものをコピペします。
また、ここからはフォルダ構成をテンプレートに従う必要があります
作業ディレクトリ直下に.devcontainer
というフォルダを作り、その中に
- devcontainer.json
- docker-compose.yml
- Dockerfile
- requirements.txt
を格納します。
それに合わせてdocker-compose.ymlのvolumesで./
から../
に変えておきます
services: # サービスを定義しますという決まり文句
python: # pythonという名前でサービスを定義
image: python:313 # イメージのREPOSITORY名:TAG名を指定
build: . # Dockerfileを相対パスで指定
container_name: python-313 # 作成されるコンテナ名を指定
working_dir: /workspace/src # 作業ディレクトリを指定 (←コンテナ内の作業ディレクトリ
volumes: # マウントするファイルを指定する
- ../:/workspace/src # ←ここを変える
tty: true # コンテナを起動し続ける
作業ディレクトリを選んで…
もし以下のように聞かれたら作業フォルダを選びます
左下の><
からコンテナで再度開くを選んで再接続すればDocker上でのPython開発が可能です!
なお終了時は同じく右下経由からリモート接続を終了するを押さないと、コンテナが終了されず、再試行したときに名前がコンフリクトしてエラーとなります。
その際はBashからDockerコマンドを用いて稼働しているコンテナを止めてあげる必要があります。
この手順でWindows+Docker+VScode+Pythonでの開発環境ができました。
Step3.5 WSLのDockerからDockerコンテナを開く
Docker for Windowsはプランによっては有料であることから、Linux向けのDockerを使用することが好まれます。
上のリンクを参考にWSL2をインストールし、WSL2経由でDockerをインストールします。
WSL2にログインし、そこのコマンドプロンプトから作業ディレクトリに移動します。
そこからcode .
コマンドを打つことでWSL経由でVScodeを開くことができます。
あとはStep3と同じ手順でWSL上で稼働するDockerの中でのPython開発ができました。
ただしこの手法だとWSL上のフォルダでは作業できても、Windows上に作成している作業フォルダではエラーが発生してしまいます。
なので以下を参考にDev Containers(開発コンテナ)拡張機能のExecute in WSLタグを有効化します。参考にしたURLでは多分GUIに関する設定についても言及されていましたが、自分には理解できなかったのと、これでWSL上のDockerコンテナにアクセスできたのでいいことにします。 CLIから逃げるな
これで作業フォルダにてcode .
コマンドを打ち、Dockerコンテナを(自動的に)起動・接続することで
WSL上で稼働するPython実行環境を持ったDockerに、Windows上のVScodeから接続して開発することが可能となります。
Step4 GPUが動作するようにする
PCにnvidia-driverがインストールされていない場合は上記URLから自分の環境にあったドライバをインストールします。ドライバが古い場合はCUDAとのバージョンエラーが起きるので更新も検討してください。更新した場合はWSLも再起動しましょう。
WSL上のDockerを使用する場合は続いてnvidia-Container-Toolkitをインストールします。
(Windows版のDockerを使用する場合には不要なようです)
自分の環境に合わせたコマンドをポチポチしていくだけです。
自身のLinuxディストリビューションに加え、Dockerインストール後にやるやつ(同ページの下の方にある)のコマンドも実行しましょう
うまくいかないときは以下のファイルをいじってみるといいかもしれません
/etc/nvidia-container-runtime/config.toml
内の以下
no-cgroups = false/true
Step5 ローカルGPU上でPyTorchを実行できるようにする
まずPyTorchの方から欲しいPyTorchのバージョンと対応するCUDAを選びます。
今回は2.7.0(安定板)、Windows、PIPインストール、Python版、CUDA12.8を選んでみました。
Run this Commandでpip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
と表示されました。
これをこのままrequirements.txtに書き込んでしまうとエラーが出てしまうので以下のように書き換えました。
torch --index-url https://download.pytorch.org/whl/cu128
torchvision --index-url https://download.pytorch.org/whl/cu128
torchaudio --index-url https://download.pytorch.org/whl/cu128
続いてDocker hubからCUDAのイメージを選びます
base: 事前ビルドされたCUDAアプリケーションを展開するための最小構成のイメージ。CUDA Toolkit 9.0以降のみ。
runtime: CUDA toolkitから全ての共有ライブラリを追加したCUDA実行用のイメージ。
devel: 共有ライブラリだけでなくコンパイラーチェーン、デバッグ用ツール、スタティックライブラリなどが追加されたCUDA開発用のイメージ。
以下より引用
# CUDA 12.8 + Python 3.13 環境
# nvidia/以下のcuda~から、Docker hubから探してくるといいでしょう
FROM nvcr.io/nvidia/cuda:12.8.0-cudnn-runtime-ubuntu24.04
# 作業ディレクトリ
WORKDIR /script
# タイムゾーンの選択を自動化する
ENV DEBIAN_FRONTEND=noninteractive
RUN ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && echo "Asia/Tokyo" > /etc/timezone
# 必要なツールをインストール
# 比較的新しいバージョンのPythonはaptの公式のライブラリに存在しません
# なので新しいPythonが必要な場合はそれがあるディストリビューションからとってきます
# セキュリティ上の問題がある場合は自力でコンパイルすことになるかと思います
RUN apt-get update && apt-get install -y \
software-properties-common \
wget \
git \
build-essential \
curl \
&& add-apt-repository ppa:deadsnakes/ppa \
&& apt-get update && apt-get install -y \
python3.13 \
&& rm -rf /var/lib/apt/lists/*
# Pythonのシンボリックリンクを作成
# インストールしたPythonのバージョンと同じものを
RUN ln -s $(which python3.13) /usr/bin/python
# pipのインストール(distutils なしで問題なく動作する方法)
RUN curl -sSL https://bootstrap.pypa.io/get-pip.py | python
#requirements.txtをコンテナ内にコピーする
COPY requirements.txt ./
# 必要なPythonライブラリをインストール
RUN pip install --no-cache-dir -r requirements.txt
また、GPUを認識するようにdocker-compose.ymlとdevcontainer.jsonも書き換えます。
docker-compose.ymlではGPUを使うことを明記します。
また、devcontainer.jsonでは起動時にGPUを使用する、というコマンドを送るようにしてあげます。--shm-sizeは…よくわかりませんでした。使用せずに起動し、問題があるならある程度の値を渡してあげるのはいいかもしれません。
services: # サービスを定義しますという決まり文句
python: # pythonという名前でサービスを定義
image: cuda:12_8 # イメージのREPOSITORY名:TAG名を指定
build: . # Dockerfileを相対パスで指定
container_name: cuda_12_8 # 作成されるコンテナ名を指定
working_dir: /workspace/src # 作業ディレクトリを指定 (←コンテナ内の作業ディレクトリ
volumes: # マウントするファイルを指定する
- ../:/workspace/src # ローカルのカレントディレクトリをコンテナのworkspace/srcにマウント
tty: true # コンテナを起動し続ける
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
{
"name": "Python VScode GPU", // VScodeがコンテナに接続したときのタイトルを自由に設定
"dockerComposeFile": "docker-compose.yml", // docker-conpose.ymlファイルを指定
"service": "python", // docker-conpose.ymlファイル内に記載したサービス名を指定
"workspaceFolder": "/workspace/src", // VScode接続時に開くフォルダを指定
"runArgs": ["--gpus", "all", "--shm-size", "64gb"], //GPUを使うことを明記、--shm-sizeはよくわからん…
"customizations": {
"vscode": {
"extensions": [ // コンテナ作成時にインストールする拡張機能を記載
"ms-python.python", // python拡張機能
"ms-python.debugpy", // pythonのデバッガ
"ms-python.vscode-pylance", // pythonのインテリセンス
],
"settings": { // VScodeの設定を記載
"files.autoSave": "afterDelay" // ファイルのオートセーブ
}
}
}
}
こちらを多いに参考にさせていただきました!
Pythonのビルドはこのようにできるらしい(まだやってない)
import torch
print(torch.cuda.is_available())
print(torch.cuda.device_count())
print(torch.cuda.get_device_name())
これらでGPUが認識されていればOKです!
Step5.5(注釈)
WSL2上のDockerからGPUを触るためには、WSL2でnvidia-container-toolkitのインストールが必要なようです。
逆にDocker desktopからの場合はローカルには不要らしい??
まとめ
Dockerを用いて、Windows上のVScodeでGPUを用いたPython開発を行う方法をまとめました。
DockerfileにてGitも入れているので、ターミナルからのgitコマンドにも反応してくれます。
Dockerを使うことで、ごちゃごちゃとしてローカルを汚しがちなPython+GPUでの開発環境を作れるのは大きな魅力だと思います。Docker、Gitなど、プログラミング以外のところの勉強を多く要するのがプログラム開発のつらいところですが、この記事がDockerでの環境設定の役に立ってくれれば幸いです!
コマンドメモ
自分用チートシート。適宜追加予定です。
~Docker~
#docker hubからDocker Imageをダウンロードする
docker pull イメージ名:バージョン(latestも可だが、バージョン指定が望ましい)
#docker hub内のイメージを検索する
docker search イメージ名
#ローカルにいるDocker Imageを一覧で表示する
docker images
#Dockerイメージの作成履歴を見る
docker history イメージ名
#イメージを消す
docker rmi イメージ名
docker rmi -f $(docker images -a -q) #イメージをすべて消す
#稼働中のコンテナを表示する
docker ps
-a(--all):停止しているコンテナも表示する
#稼働中コンテナの状況をリアルタイム表示する
docker stats
#Docker imageからDocker containerを作成して実行する
docker run イメージ名
--name:コンテナに名前を付ける
-d:コンテナをバックグラウンドで動作させる
-e:環境変数をセットする
ex. -e KEY:VALUE
-p:ホストのポートとコンテナ内のポートを関連付ける
ex. -p 80:80
--rm:終了時に自動的にコンテナを削除する
-v(--Volume):ホストのPathをコンテナ内にマウントする
ex. -v ホストのパス:コンテナ内のパス
#bashを用いて指定したコンテナの中に入る
docker exec -it コンテナ名 bash
#Docker containerを止める
docker start コンテナ名 #再開
docker stop コンテナ名 #停止
docker restart コンテナ名 #再起動
docker rm コンテナ名 #削除
-f:なんかうまく消えない時に強制的に消す
docker rm ーf $(docker ps -a -q) #コンテナを全部削除
docker system prune #停止中のコンテナと無名のイメージをすべて消す
#稼働しているコンテナを強制的に全て消すとき
docker rm ーf $(docker ps -a -q)
docker rm ーvf $(docker ps -a -q) #ボリュームごと消えるので注意
#DockerImageを作成する
##起動中のコンテナからイメージを作成する
docker commit コンテナ名 イメージ名
##DockerfileからDockerimageを作成する
##作業フォルダ内にDockerfileなどの必要なファイルがあること
docker build --tag イメージ名 .
~docker compose~
docker compose build #docker-compose.ymlからのイメージのビルド
docker compose up #composeの起動
docker compose down #composeの停止
docker compose rm コンポーズ名 #composeの削除
docker compose images #作成したイメージの一覧
docker compose ps -a #起動したコンポーズの一覧(-aオプションで停止中も含む)
#すべてのDocker composeを消す
docker-compose down --rmi all --volumes --remove-orphans
~Git/Github~
git init #作業ディレクトリの初期化
git add ファイル名/. #ファイルや全ツリーを追加
git commit #追加したファイルなどをコミット
git commit --amend #現在のステージでローカルリポジトリをしゅうせい
git rm #ファイルの削除
git mv
git status #ファイルの変更状況を表示
git diff #ファイルの変更内容を表示
git checkout --ファイル名/フォルダ名/. #ローカルファイルの変更を戻す
git reset HEAD ファイル名/フォルダ名/. #
/home/.gitconfig:UserやURLなどのユーザーデータを保存
.gitignore .gitの親ディレクトリに保存、gitしないファイルなどを指定
トラブルメモ
-volumeキーワードによるWindowsのフォルダと仮想環境のフォルダをマウントできない
#-v --volumeタグにてホストのフォルダをDocker containerのフォルダにマウントできる
docker -v (windows Path):(docker container path)
#Windows PowerShellからの実行の場合は
#下記のようにPathの最初にスラッシュが2つ必要
docker run --volume //c/Users/myName/Documents/dockerTest://usr/share/nginx/html
ファイルの保存ができない
Step3.5で発生。Linux上のファイルパーミッションが影響していそう
どうしても解決できず、ファイルを作り直しました…
ファイルの作成などはVScode上でやることを徹底した方がよさそうですね…
CUDAのイメージが実行できない
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running prestart hook #0: exit status 1, stdout: , stderr: Auto-detected mode as 'legacy'
nvidia-container-cli: requirement error: unsatisfied condition: cuda>=12.8, please update your driver to a newer version, or use an earlier cuda container: unknown
CUDAのバージョン毎に最低限のnvidia driverのバージョンがありますので、必要に応じてアップデートしてください
その他参考にした資料
Udemyの講座。4時間で学べると
他、ネット上のあまたの資料と、ChatGPTに感謝します