うごくものづくりのために

技術的な備忘録がメインです。

dockerコンテナ内で動作するGUIの画面を他のコンテナで表示する方法

ほとんど需要ないと思いますが…。

xserverが動作しているコンテナ(コンテナA)に、GUIソフトが動作するコンテナ(コンテナB)を接続して、コンテナB上のGUIウィンドウをコンテナA上に転送します。

方法

まず、以下の2つを用意します。

  • コンテナA: GUIが動作する(xserverが動作している)dockerコンテナ (ubuntu-desktopなど)
  • コンテナB: GUIソフトを動作させるdockerコンテナ

今回は、コンテナAはuphy/ubuntu-desktop-jpを、コンテナBは gns3/xeyes を使います。

https://hub.docker.com/r/gns3/xeyes

https://hub.docker.com/r/uphy/ubuntu-desktop-jp


まず、コンテナAを起動します。

sudo docker container run -it --rm --name container-a -p 8080:8080 -v /tmp/.X11-unix uphy/ubuntu-desktop-jp:latest

uphy/ubuntu-desktop-jpでは、 http://localhost:8080/に接続することでnoVNC経由で画面が表示できます。 確認しておきましょう。

次に、コンテナBを起動します。

sudo docker container run -it --rm --name container-b -e DISPLAY=:0.0 --volumes-from container-a gns3/xeyes

うまくいっていれば、コンテナAの画面(http://localhost:8080/)に、カーソルを追いかける目玉が表示されているはずです。

f:id:tilt_silvie:20190114144104p:plain

仕組み

ミソは2つあります。

1つめのミソは、/tmp/.X11-unixのコンテナ間での共有です。
/tmp/.X11-unixは、xserverとxclientの間の unix domain socketです。要はこのソケットを通じて、GUIを表示したいソフト(xclient)とその処理をするxserverとの間で情報をやりとりしています。
今回は、コンテナA内の /tmp/.X11-unixを、dockerのData Volume機能を使ってコンテナBに共有することで、あたかもコンテナBがxserverを起動しているかのような状態にしています。

2つめのミソは、環境変数DISPLAYの定義です。 コンテナB起動時の -e DISPLAY=:0.0 がそれです。
DISPLAYはxserverのパスを指定するための環境変数ですが、今回はコンテナBにコンテナAの/tmp/.X11-unixをマウントしているので、ローカルに画面があるときと同じ:0.0としています。

参考

Dockerコンテナの中でGUIアプリケーションを起動させる | Unskilled?