💻

docker内でGUIを使おうと色々した話

createdAt
2023-02-11
reading time
8 min read

はじめに

最近 Docker 内で GUI を使おうと思い色々調べたので、それのメモです。

参考までに筆者の環境は以下のとおりになっています。

  • OS
    • Windows 11 Home 22H2
  • WSL(一部割愛)
    • WSL バージョン: 1.0.3.0
    • カーネル バージョン: 5.15.79.1
    • WSLg バージョン: 1.0.47

      wsl -v で確認できます。ない人はwsl --update をしてみてください

  • Docker
    • Docker Desktop 4.16.3
    • Docker version 20.10.22
    • Docker Compose version v2.15.1

今回はWSLgを使う例、およびVNCを使う例を紹介します。

WSLg を使う方法

WSLg is 何?

WSL その 222 - Linux GUI アプリを動かす WSLg のアーキテクチャーと仕組みを見るとなんとなく御理解いただけるのではないかなと思います。

WSLg-diagram

上記ブログでも紹介されているMicrosoft のブログから図を拝借してきました。普段使用しているディストリビューションの一部が書き換えられて、裏で動作している GUI 用のサーバーに接続しているようです。そしてこのサーバーからリモートデスクトップを使ってホスト(つまり Windows)と通信しているのだと思います。

図を見て「X とは?」となった方はgihyo 様の記事を確認すると何となく理解できると思います

試しにDISPLAYなどの環境変数を見てみると

Terminal window
$ printenv DISPLAY WAYLAND_DISPLAY XDG_RUNTIME_DIR PULSE_SERVER
:0
wayland-0
/mnt/wslg/runtime-dir
/mnt/wslg/PulseServer

確かに GUI 用のサーバーに接続するように設定されているようです。

Docker の設定

以下のようなDockerfilecompose.yamlを準備してください、「Docker Compose なぞ使わねえ!」という方は適時docker -vなどに読み替えてください。たぶん動くと思います。

  • Dockerfile
# devcontainerを使いたかったのでこのイメージを使ってますが、
# 通常の用途では`ubuntu:20.04`とかを使うといいと思います
FROM mcr.microsoft.com/vscode/devcontainers/base:debian
# 動作確認用です。不要なら削除してください
RUN apt-get update -y && \
apt install -y \
x11-apps
  • compose.yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
command: sleep infinity
environment:
- DISPLAY=$DISPLAY
- WAYLAND_DISPLAY=$WAYLAND_DISPLAY
- XDG_RUNTIME_DIR=/tmp
- PULSE_SERVER=$PULSE_SERVER
volumes:
- type: bind
source: /tmp/.X11-unix
target: /tmp/.X11-unix
- type: bind
source: "${XDG_RUNTIME_DIR}/wayland-0"
target: /tmp/wayland-0

docker compose upしてコンテナを立ち上げ、docker compose exec app bashでコンテナ内に入ります。

一応ここでも環境変数がどうなっているか軽く確認します。

Terminal window
$ printenv DISPLAY WAYLAND_DISPLAY XDG_RUNTIME_DIR PULSE_SERVER
:0
wayland-0
/tmp
/mnt/wslg/PulseServer

ちゃんと設定されている風ですね。試しにxeyesを使ってみます。

Terminal window
$ xeyes

xeyes実行結果

ちゃんと画面が出てきました!!。軽くしか試していませんが2つ以上ウィンドウを立ち上げても問題ないようです。

2つのウィンドウ

docker 内で日本語化の設定などをすれば、おそらく日本語入力などもできると思います(未検証)。

VNC を使う方法

そもそも大抵の要望は 👆 のWSLgで問題ないと思います。なのでほとんどの方はここを読む必要がありません。ですが特定のユースケース、例えばスクリーンショットを取る等の必要があればこちらを選ぶと良いと思います。

VNC is 何?

調べる中でVNCを使ってもできるという情報があったのですが、私はそもそも初めて聞く言葉だったのでちょっと調べます。

辞書によると、RFB と呼ばれるプロトコルを用いてデスクトップ画面や、キーボードなどの入出力をネットワーク越しに通信するソフトウェアの総称だそうです。音声通信も調べた限りできるっぽいです。

Docker の設定

これに関してはいい感じのイメージがあったのでこれを使えば以下の面倒な設定は不要です。

今回は自分で組む経験を積みたいので Dockerfile から書いていきます。

(再掲)以下のようなDockerfilecompose.yamlを準備してください、「Docker Compose なぞ使わねえ!」という方は適時docker -vなどに読み替えてください。たぶん動くと思います。

  • Dockerfile
# devcontainerを使いたかったのでこのイメージを使ってますが、
# 通常の用途では`ubuntu:20.04`とかを使うといいと思います
FROM mcr.microsoft.com/vscode/devcontainers/base:debian
ENV DISPLAY=:1
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y && \
apt install -y --no-install-recommends \
x11-apps \
# 好みで適当なGUIに変えてください
lxde \
# 好みでここも好きなVNCに変えられます
tigervnc-standalone-server \
tigervnc-common \
# NoVNC
novnc \
websockify
  • compose.yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
command: sleep infinity
ports:
- 7001:80

先ほどど同様の手順でコンテナ内に入り、TigerVNC or お好きな VNC を起動します。

TigerVNC

Terminal window
$ USER=root vncserver :1 -geometry 800x600 -depth 24

vncserver

rootでユーザを作成し解像度 800x600 の VNC デスクトップを立ち上げています。depthの意味はよくわかっていません。パスワード入力してくださいと言われたら、適当なパスワードを設定します。

vncserver -listで現在の VNC デスクトップを確認できます。また、vncserver -kill :xで対象の VNC デスクトップを削除できます。

vnclist

5901 番のポートにサーバーが立っているので、localhost:5901 を指定します。

Terminal window
$ websockify -D --web=/usr/share/novnc/ 80 localhost:5901

websockify

ここまで実施したら、ホスト PC からlocalhost:7001/vnc.htmlにアクセスすると…

novnc

NoVNCの画面が表示されるので、Connect を押して先程設定したパスワードを入力します。すると、コンテナ内の GUI が表示されます。

guiからxcalc

👆 はxcalcを実行してみた例です。コンテナ内のターミナルから実行しても問題なく表示されています。

terminalからxeyes

ブラウザだけで GUI が使えるのは便利です。

音声について

この IssueよるとNoVNC は音声もサポートしている or その実装があるっぽいですが、そもそも VNC 側で対応しているサーバが少ないようです。

音声だけは上のWSLgでやったようにPULSE_SERVERで送るのがいいかもしれませんが、今回は検証していないので実際にできるかどうかわかりません。

終わりに

WSLgを使った例は Mac を使っている方にはできないので、そういう意味ではVNCを使ったほうが良いのかもしれませんが、 パフォーマンス的なあれそれがちょっと気になります。そもそも、Docker と GUI の相性があまり良くないのかもしれません。

参考

これは以下の素晴らしい記事を参考に作成されました。