MkItYs

MkItYs > ネットワークとサーバを作る > 

images

高機能のウィンドウシステム:X Window System (XQuartz) , Docker, OpenGL, Tcl/Tk, Xvfb, x11vnc

images

- 2022.09.16

Xウィンドウは、パソコンやサーバにGUI(言葉でなく画像での操作)を提供する、基本アプリのひとつですーークライアント〜サーバ・モデルの採用や、柔軟なカスタマイズ性など、ほかのウィンドウシステムにはない特徴があります。[※1]


※1
ただ細かい部分ではあつかいにくい面もあり、いまは、これをより洗練させたモデル(Wayland )が提案〜実装されています(とはいえX Window のプロトコルも受け付けられるよう、サブシステムとして残されています)。

検証


ローカル
OS:macOS 11
ウィンドウシステム:XQuartz 2.8
コンテナ:Docker 20.10 (Docker Desktop)
リモートホスト
OS:Ubuntu 20.04
コンテナ:Docker 20.10

GUIの基本アプリ:X Window


Xウィンドウは、パソコンやサーバにGUIを提供する、基本アプリのひとつです。

その大きな特徴は、クライアント〜サーバ・モデルになっている、という点にありますーーXウィンドウは、グラフィックを送信する「Xクライアント」と、グラフィックを表示する「Xサーバ」に分かれますーーこうすることで、たとえばビデオモニタがない(ヘッドレスの)リモートホストで動いているXクライアントの描画を、ローカル(自分のパソコンなど)のXサーバの画面に表示させる、といったことができるようになります。[※1][※2]


※1
つまりウィンドウ単位で、遠隔操作ができるわけです。しかもIPネットワークに対応しているので、原理上はインターネット上のどのノードでも、XサーバとXクライアントになれます(ただし現状のネットーワークは、NATといった制約があるのでやっかいですが)。
※2
カスタマイズが自在であることも、特徴のひとつですーーウィンドウの枠の形や色、ボタン類の有無や配置まで、柔軟に変更できます(たとえばボタン類をいっさい廃して、枠とキーのショートカットだけでウィンドウを操作する、といったこともできたりします……見た目かなりシンプルになりますよ)。

GUIの基本アプリ:個別:X Window (XQuartz)


マック(macOS )向けのXウィンドウ(XQuartz )は、次にあります:

https://www.xquartz.org/

遠隔のサーバやコンテナ上のXクライアントからの接続を許可するには、次を設定しておきます:

環境設定 > セキュリティ
> 接続を認証: <yes>
> ネットワーククライアントからの接続を許可: <yes>

標準のCGライブラリ(OpenGL)は、既定では有効になっていません。これを使うには、次を設定し、ウィンドウシステムを再起動します:

$ defaults write org.xquartz.X11 enable_iglx -bool true

Xサーバの設定


Xサーバ側は、Xクライアントからの描画要求を受けつけるよう、認証させる必要があります。基本は、相手のIPアドレスやホスト名を指定します。

たとえば、ローカルで動いているXクライアントに対しては:

$ xhost +localhost

Xクライアントの設定(ローカル:コンテナの場合)


ローカルのコンテナ上で動いているXクライアントからの描画要求を受けられるようにするには、Xウィンドウの表示デバイスとソケットとを共有します:

ローカル:
$ docker run -it --rm \
--env DISPLAY=${DISPLAY} \ # ホスト側の表示デバイスを引き継ぐ
--mount type=bind,src=/tmp/.X11-unix,dst=/tmp/.X11-unix \ # ホスト側のソケットを共有する
--name ${container} \
${image}

Xクライアントの設定(ローカル:コンテナ:仮想環境の場合)


コンテナが仮想環境の上で動いている場合(macOS やWindows の一部)、ローカルのXサーバとは、表示デバイスやソケットを共有できません。代わりに、特別な表示デバイスをコンテナ側が用意しているので、これを使います:

ローカル:
$ docker run -it --rm \
--name ${container} \
${image}
コンテナ:
$ export DISPLAY=host.docker.internal:0.0

Xクライアントの設定(リモートホスト:コンテナの場合)


XウィンドウがIPネットワークに対応しているといっても、現在のネットワークでは、リモートにXクライアントがある場合、ローカルのXサーバに向けて直接通信できないこともよくあります(内側のアドレスが変換されてしまう、NATなどにより)。

ローカル側から、リモートのコンテナにあるXクライアントにつなぐ手法には、SSHによるポートフォワーディングがあります:[※1]

リモートホスト:
$ cd /etc/ssh
$ cat sshd_config | grep '^X11Forwarding'
X11Forwarding yes
$ docker run -it --rm \
--env DISPLAY=${DISPLAY} \ # ホスト側の表示デバイスを引き継ぐ
--net host \ # ホスト側とネットワークを共有する
--mount type=bind,src=${HOME}/.Xauthority,dst=/root/.Xauthority \ # ホスト側のXウィンドウの認証ファイルを共有する
--name ${container} \
${image}
ローカル:
$ xhost +${server_remote} # 許可:リモートホスト
$ ssh -X ${user_remote}@${server_remote} # 接続:リモートホスト

※1
この場合、リモートホストにファイアウォールを適用していなければ、リモートホストのホストに、どこからでもSSHで接続できる状態になります……かといってプロバイダ経由だと、IPアドレスが自動で割り当てられるので、ファイアウォールでそれなりに範囲を絞ることはできても完全に防ぐことは難しいですしね……VPNサーバを立ち上げて、そこを経由してアクセスする、などの方法はありますが……

Xクライアントの設定(リモートホスト:コンテナ:マルチユーザの場合)


ホスト側のネットワークを独占しない場合は(ルートレスのコンテナなど)、コンテナ内でSSHサーバを稼働させ、そこにXフォワードします:

リモートホスト:コンテナ:
$ apt install openssh-server # SSHサーバを導入〜設定
$ echo 'PermitRootLogin prohibit-password' >> /etc/ssh/sshd_config
$ echo 'X11UseLocalhost no' >> /etc/ssh/sshd_config

$ cd /root
$ mkdir .ssh
$ cd /root/.ssh
$ vi authorized_keys # 自身の公開鍵を記載

$ /etc/init.d/ssh restart # いったん起動し、既定の設定を生成
リモートホスト:
$ docker run -d --rm -p 10023:22 --name ${container} ${image} /usr/sbin/sshd -D # SSHサーバとして起動(ホスト側の空いているポートで受け付け)
ローカル:
$ ssh -X -p 10023 root@${server_remote} # Xフォワーディングでコンテナに接続

Xクライアントの設定(リモートホスト:コンテナ:VNCの場合):Xvfb, x11vnc


ローカル側でXサーバを動かしたくないなら、VNCクライアントを使う、というやり方もあります。

リモートホストのコンテナでXサーバを動かし、そのXサーバの描画要求をVNCサーバに渡します。そのVNCサーバに、ローカルのVNCクライアントから接続します:[※1]

Xサーバ:Xvfb
VNCサーバ:x11vnc
リモートホスト:コンテナ:
$ export n=1
$ export DISPLAY=:${n}
$ Xvfb :${n} -screen 0 600x450x24 &
$ x11vnc -display :${n} -forever -passwd ******** &

※1
マック(macOS )の標準VNCクライアントの場合、次のオプションは必須です:-forever, -passwd

遠隔からデスクトップを使う[検証中


遠隔からデスクトップを使うには、Xサーバをネストする(Xサーバ兼Xクライアント)アプリを使うことで、実現できます:[※1][※2]

SSHからポートフォワードした遠隔の端末で、次のように実行します:

$ Xephyr :1 &
$ DISPLAY=:1 gnome-session # デスクトップ環境がGNOME の場合
$ DISPLAY=:1 startkde # デスクトップ環境がKDE の場合

※1
Xephyrは、Xnest の後継です。
※2
ただしキーマップやセッションの管理がややこしく、現時点ではうまく動かせていません(2022.10.16)。

GUIの開発環境:Tcl/Tk


Xウィンドウで動くGUIのアプリを作るために、専用のツールキット「Tcl/Tk」が用意されています。

このうち「Tk」は、APIを提供します。「Tcl 」は、そのAPI操作するスクリプト言語のひとつです(「Tk」に対しては、ほかにさまざまなスクリプト言語(Python, etc.)も対応しています)。