Docker上のGUIアプリをホスト/リモートで描画する
今回は、リモートUbuntuサーバーのDockerコンテナ上で起動しているGUIアプリの画面を、ホスト自身やローカルのMac/Windowsのディスプレイに表示させる方法についてまとめてみます。
筆者は環境構築を楽に済ませるためにDockerを利用することが多いのですが、デフォルトのDockerコンテナではGUIを表示させることができないので、画像の確認やGUIアプリが付属しているOSSの動作確認をするときに不便です。
そこでコンテナ内でX11対応のアプリを起動し、それをローカル側にforwardすることでGUIを表示させてみます。
※ 2020/06/02 : 申し訳ないことにX11の仕様を誤解していました。解説の中でクライアント/サーバーが逆になっていた部分を修正しました。
【2021/02/07 追記】
今回紹介するX11 Forwardingは、手軽に使える反面、複数のウィンドウが立ち上がるアプリを使うときに不便なのと、遅延が大きいのがネックになります。
「コンテナの容量と計算負荷は増えていいから、本格的なデスクトップ環境を使いたい」という方は、以下の記事で紹介するVNCによるリモートデスクトップの方がニーズに合っているかもしれません。
もくじ
スポンサーリンク
1. 環境
Ubuntuサーバーの上でDockerコンテナを立て、Mac/WindowsからSSHログインしてdocker exec -it xxxx bash
している状況を想定します。
Host : Ubuntu 18.04 Docker Community : 19.03.2 Local Mac : macOS Mojave 10.14.6 XQuartz 2.7.11 Local Windows : Tera Term 4.104 VcXsrv 1.20.5.1
2. X Window Systemとは
最初に、今回利用するX Window Systemについて軽くおさらいしておきます。
X Window SystemはOSがGUIを提供するために利用するウィンドウシステムの一種です。 1987年以降、バージョン11が安定版となっているのでX11と呼ばれることもあります。
描画の原理としては、
- GUIを表示するマシン上でX11サーバーを立ち上げる
- GUIを提供するアプリがX11クライアントを立ち上げ、X11サーバーと接続する
- サーバーとクライアントが通信しながら描画・キーボード/マウス入力を処理する
という流れになっています。 サーバーとクライアントはネットワーク越しに通信できるため、別のコンピュータで動作するGUIアプリを手元のコンピュータで描画することもできます。 このことをX11 Forwardingと言います。
X11はUnix系OSにおける標準的なウィンドウシステムとして採用されています。 またWindowsやMacOSは独自のウィンドウシステムを実装しているのですが、X11規格のGUIを描画するためのソフトウェアも提供されているため、環境を整えればX11のGUIを扱うことができます。
3. Docker上のGUIアプリを描画する方法
3.1. Macから接続する場合
- XQuartzをインストールする(公式サイト)
- ターミナルから
ssh -Y xxxx@xxx.xxx.xxx.xxx
でUbuntuに接続する-Y
はX11 Forwardingを有効にするためのオプション
-e DISPLAY=$DISPLAY --net host -v /tmp/.X11-unix:/tmp/.X11-unix -v $HOME/.Xauthority:/root/.Xauthority
のオプションを付けてDockerコンテナを作成する
以上で設定完了です。
あとはコンテナ内でX11を利用するGUIアプリを起動させると勝手にXQuartzが起動し、手元でGUIが描画されます。
一番手軽に試せるのはapt install x11-apps
でインストールできるテストアプリxeyes
, xclock
, xcalc
, etcです。
OpenCVをインストールしてimshow
してみるのもアリです。
またDockerコンテナを立ち上げた後にSSH接続するとXサーバーとクライアントの通信に失敗します。
具体的にはX11のアプリを立ち上げようとした段階でX11 connection rejected because of wrong authentication.
というエラーが出ます。
はっきりした原因はわかっていないのですが、おそらくクライアントがサーバーの認証情報をうまく拾えていないのだと思います。
新しくSSH接続した後でX11 Forwardingする場合は、対象のコンテナを一度docker restart
させる必要があります。
3.2. Windowsから接続する場合
- VcXsrvをインストールする(公式サイト)
- Tera Termをインストールする(公式サイト)
- Tera Termを起動させ Setup > SSH Forwarding > Display remote X applications on local X server にチェックを入れた上で Setup > Save setup からTeraterm.iniに現在の設定を上書き保存する
- VcXsrvを起動させる
- デスクトップにショートカットが作成されているはずなのでそれをダブルクリック、すべての設定をデフォルトのままNextをクリックしていけばOK
- クライアントが起動すると画面右下にVcXsrvのアイコンが表示されるようになる
- Tera Termを再起動させUbuntuにSSHログイン
あとはMacと同じ要領でDockerコンテナを作成し、コンテナ内でGUIアプリを起動するだけです。
3.3. ホストで表示する場合
Dockerを起動しているUbuntuのデスクトップに表示させるのは結構簡単です。
- ターミナルで
xhost +local:docker
を実行する
これだけです。
あとはMacと同じ要領でDockerコンテナを作成し、コンテナ内でGUIアプリを起動すればOKです。
4. 後から表示先を変えたい場合
X11クライアントは環境変数DISPLAY
に設定されたアドレスのサーバーに画面をForwardするので、この環境変数を変更すれば表示先を切り替えることができます。
UbuntuサーバーにSSHログインした直後にecho $DISPLAY
を実行すると:1
, localhost:10.0
などの文字列が表示されます。
これはディスプレイのアドレスを表しており<IP>:<ディスプレイ番号>.<スクリーン番号>
を基本として逐次省略形が使われています。
ここで表示された文字列を覚えておき、docker exec -it xxxx bash
した後でコンテナ内でDISPLAY=localhost:10.0
のように変数を上書きすることで、Forwardするサーバーを変更できます。
以上、Dockerコンテナ内のGUIアプリを描画する方法をまとめました。
今回はLAN内のサーバーに接続することを前提にしていましたが、LAN外のコンピュータに接続する場合は適宜ファイアウォールを調整すべきですね。