先端技術部
テクニカルスペシャリスト 黒住 好忠
こんにちは。テクニカルスペシャリストの黒住です。
これまで「Windows 10 + WSL + Windows版のDocker Desktop」というコンテナ環境を多用していましたが、Windows 11が登場してから「Windows 11 + WSL + WSL上のdocker-ce + nvidia-docker2」という環境に移行しました。
そして、WSL上のDockerを使う上で悩みの種だった「OpenCVなどのGUI画面を表示できない」という課題も、Windows 11から解消されました。そこで今回は、「WSL上で動かしているDockerコンテナからGUI画面を表示する方法」についてご紹介しようと思います。
WSL上のDockerコンテナからGUI表示
Windows 11 build 22000以降、WSLg(Windows Subsystem for Linux GUI)という機能を使って、「WSL上でGUIアプリケーションを実行」できるようになりました。
公開されているWSLgに関する情報は、「WSL上でLinuxのGUIアプリケーションを動かす方法」に関する内容が多いのですが、実は「WSL上のDockerコンテナで動いているアプリケーションでもGUI表示が可能」になります。(WSL上のアプリではなく、WSL上のDockerコンテナで動いているアプリという点がポイント)
つまり、WSLgを使えば、今までは実現できなかった「WSL上で動くDockerコンテナから、OpenCVなどを使ったGUI画面の表示」が簡単に実現できるのです。
早速、DockerコンテナからWSLgを使ってGUIを表示する方法を見ていきましょう。
docker composeの設定
Windows 11でWSLが最新の状態になっていれば、Docker側の設定に「WSLgと連携できるような定義を追加」すると、Docker側からWSLgが利用できるようになります。
以下に、具体的なdocker-compose.yml
の設定例を示します。
version: "3.9"
services:
py3:
build:
context: ./py3
dockerfile: Dockerfile
working_dir: /workspace
entrypoint: ["python", "app.py"]
volumes:
# Workspace
- ./workspace:/workspace
# WSLg
- /tmp/.X11-unix:/tmp/.X11-unix
- /mnt/wslg:/mnt/wslg
environment:
# WSLg
- DISPLAY=$DISPLAY
- WAYLAND_DISPLAY=$WAYLAND_DISPLAY
- XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR
- PULSE_SERVER=$PULSE_SERVER
# GPUを使うための設定
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
# GPUを使うための設定
deploy:
resources:
reservations:
devices:
- capabilities:
- gpu
WSLgとは関係のない部分も含まれていますが、ポイントは volumes
と environment
に「# WSLg」というコメント付きで記載している部分になります。
volumes
で、 /tmp/.X11-unix
と /mnt/wslg
のマッピングを行い、environment
で、 DISPLAY
, WAYLAND_DISPLAY
, XDG_RUNTIME_DIR
, PULSE_SERVER
という環境変数の定義を行います。
なお、上記サンプルでは「docker compose」を前提としていますが、同様のマッピングと環境変数の設定を行えば、Docker単独でもWSLgの利用が可能だと思われます。
この状態で、例えば以下のようなOpenCVを使ったPythonコードを実行すれば、「Windows側にOpenCVのGUI画面が表示」されます。また、GUI画面の表示だけでなく、画面に対するマウスやキーボードの操作なども通常通り行うことができます。(WSLgが登場した当初は、2回目以降の起動時に前回押していたキーが押されたままの状態になる不具合が存在していましたが、現在はこの問題は解消されています)
import cv2TITLE = "docker on WSL2"cv2.namedWindow(TITLE, cv2.WINDOW_AUTOSIZE)# 画像表示img = cv2.imread("fireworks.jpg")cv2.imshow(TITLE, img)print("ESCキーを押せば終了")while True:if cv2.waitKey(1) == 0x1B:breakcv2.destroyAllWindows()
図:Windows側に表示されたGUI画面(処理自体はWSL上のDockerコンテナで動かしている)
上記の docker-compose.yml
や app.py
を含むサンプルコード一式は、以下のGitHubリポジトリで公開しているので、必要に応じて参照してみてください。
(※外部リンク)GitHubリポジトリ
最後に
今回は、「WSL上のDockerコンテナからGUI画面を表示する方法」について取り上げてみました。
紹介したサンプルは「GUI画面を表示するPythonコードの実行」という内容でしたが、Dockerコンテナ上で実行しているJupyterLabなどに「ブラウザ経由で接続している場合でも、WSLgは利用可能」です。
また、今回は取り上げていませんが、Windows 11では「WSLの初回起動時にdockerサービスを自動で起動」させたり、「WSL上からWebカメラなどのUSBデバイスをUSBIP経由で利用」することも可能なので、色々試してみてくださいね。
※ただしUVCデバイスを/dev/video*として認識させるためにはカーネルのビルドが必要になります。
開発環境についても、JupyterLabなどを利用する方法以外に、VSCodeからRemote-Containersという拡張機能を利用して、直接WSL上のDockerにアタッチした状態での開発も可能なので、目的や用途に合わせて使い分けてみてください。
それでは、また次回のコラムでお会いしましょう。
参考リンク
記事に関連する参考リンクです。(※いずれも外部リンク)
- 上記で紹介したサンプルコード一式(GitHub)
- WSL関連
- docker関連
- VSCode関連