理解しながら動かすGUIアプリ on Docker

「パソコンが立ち上がらない」という相談に駆けつけてみると押していたのがディスプレイの電源スイッチだったというジョークがありますが、Xがわからなかった私はこのジョークを笑う資格はありませんでした。

怒り散らかしながらディスプレイの電源スイッチを連打するレベルからレベルアップし無事Xのシステムを完全に理解し(※)、リモートGPUサーバのk8s上で動くアプリのGPUアクセラレーションを有効にしてクライアントからのぞくことに成功し、ある程度消化できたので、ハードウェアアクセラレーションを使わない範囲での仕組みについて、まとめを書きます。

※ ダニング＝クルーガー効果なので気にしないでください


# LinuxのGUIシステム
LinuxのGUIの仕組みは現在進行系でも進化しており、近年また大きな変化の波が押し寄せています(Wayland)。今のところ新しい仕組みよりも枯れた方が知見が多く見つけられるので、XOrgという仕組みを前提にします。
[LPIC-1 v5 - 106 User Interfaces and Desktops](https://learning.lpi.org/en/learning-materials/102-500/106/106.1/106.1_01/)に詳しいです。Ubuntuが起動しLinux操作時にGUIが表示されて手を叩いて喜んでいるとき我々はLCDを見ています。このLCDに表示されている内容はDRMを通してカネールが指示をしてVRAMにレンダリングされたものです。

![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117379/39720e81-1747-87b9-9226-7edeffc6c456.png)

このとき、デスクトップ(= ウィンドウ)、GUIのウィンドウ、クライアント領域内の「絵」はWindow Managerがコンポジット(合成)してくれた内容で、XServerにアプリケーションからUnix Domain Socketを通してリクエストしたものです。

# Dockerコンテナ内GUIアプリをLinuxホストで表示

同様にDockerコンテナでGUIアプリケーションを動かすときには、DockerコンテナからUnix Domain Socketを透過させてホスト側のX Serverにリクエストを出すことで実現します。

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117379/819ec7a6-d23f-d683-65c2-7b176e200665.png)

XServerへのアクセス権限管理があり、コンテナ内アプリに与えるユーザー権限に気を使う
[事例](http://wiki.ros.org/docker/Tutorials/GUI)もあります。

```
docker run -it \
    --user=$(id -u $USER):$(id -g $USER) \
    --env="DISPLAY" \
    --volume="/etc/group:/etc/group:ro" \
    --volume="/etc/passwd:/etc/passwd:ro" \
    --volume="/etc/shadow:/etc/shadow:ro" \
    --volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    [イメージ名] \
    [GUIアプリ]
```

# Windows 11 WSLg
さて、ここで今ではWindows11だけで(?)使えるWSLgという仕組みを差し込ませてもらいます。これもかなり込み入った仕組みだけれどもXの仕組みを理解するのに大事な内容で、それまで仮想ネットワークを通してTCPパケットを通じてアプリケーションを表示していました ([WSL2におけるVcXsrvの設定 \- Qiita](https://qiita.com/ryoi084/items/0dff11134592d0bb895c))

![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117379/58c187a5-b8d8-1651-0e13-b992ce5fbbff.png)

これが[Windows 10でオーディオやグラフィックスアプリを含むLinuxのGUIアプリを使用可能にする「WSLg」機能が登場 ](https://gigazine.net/news/20210422-linux-gui-application-run-on-windows-wslg/)したことにより、大幅変わったのです。

じゃーん。

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117379/8b2cee4d-858b-03d3-86b0-0fe00ae4e5b6.png)

基盤に新世代のXの仕組みwaylandを採用し、旧来型のXOrg的なアプリケーションとのコミュニケーションにはトランスレータ(XWayland)を挟んでおります。Windowマネージャーの役割はWaylandの標準実装通りWestonに取り込まれました。ここで注目すべき(?)はRDPの存在で、これまでのWindowsのリモートデスクトップの枠組みを拡張して（？）、VAILやRAILといった仕組みでデスクトップではなくWindowレベルでの「リモートデスクトップ」を実現しているということです。

この他、Xパケットの転送のみでは実現できなかった「音情報」の転送も組み込んでいます。

# Docker on WSL2 on Windows 10?
Docker Desktopを企業活動で利用するのが有料になったことから、[Docker Desktop を使わずに Windows で Docker する \- プログラム の超個人的なメモ](https://dk521123.hatenablog.com/entry/2021/11/14/224428)という魔術が出回るようになりました。このアーキテクチャの場合、TCPでX11 Protocolを書き出しているので、Unix Domain Socketではなく、ポートフォワードで実現するのかなと思います（未確認）

![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117379/e5af1c2e-e5aa-c574-5a05-813f99c8fb65.png)


# 参考文献
- [LPIC-1 v5 - 106 User Interfaces and Desktops](https://learning.lpi.org/en/learning-materials/102-500/106/106.1/106.1_01/)
- [i3 \- improved tiling wm](https://i3wm.org/)
    - `This includes being modifiable by people who do know how to program but who are not necessarily familiar with all of X11’s internals. `とのことだ、おい。
- [Wayland](https://wayland.freedesktop.org/architecture.html)
- [Direct Rendering Infrastructure \- Wikipedia](https://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure#History)
- [WSLg Architecture \- Windows Command Line](https://devblogs.microsoft.com/commandline/wslg-architecture/)