macOS上でX11アプリを起動する（Docker + Xvfb + VNC）

<img width="752" alt="connected.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58479/3bb5802e-68f9-bbad-7607-05854c603947.png">

## 1. 概要

　macOS上でX11環境を必要とするアプリを実行したいこと、たまにありませんか？僕はあります。
macOS上のX11環境（XQuartz）を利用するのも1つの手ですが、もっと手軽に使えないかと、Docker、Xvfb、VNCを組み合わせる方法を試してみました。
まだ詳細な検証は行っていませんが、問題なく利用できそうです。

## 2. 使用するソフトウェア

　今回使用したソフトウェアは以下の通りです。

* Docker
    * 言わずと知れたコンテナ型の仮想化を行うソフトウェアです。
    * 英語版Wikipedia: https://en.wikipedia.org/wiki/Docker_(software)
* Xvfb: X virtual framebuffer
    * 仮想的なフレームバッファ（描画先）を持つディスプレイサーバです。X11プロトコルをサポートしており、実際のディスプレイ環境とは独立したフレームバッファを作ることができます。
    * 英語版Wikipedia: https://en.wikipedia.org/wiki/Xvfb
* VNC: Virtual Network Computing
    * いわゆる「リモートデスクトップ」を実現するためのソフトウェアの1つです。
    * 英語版Wikipedia: https://en.wikipedia.org/wiki/Virtual_Network_Computing

## 3. 環境

　今回試した環境は以下の通りです。

* ホスト:
    * OS: macOS Mojave 10.14.5
    * Docker Desktop for Mac: 2.1.0.1 (37199)
        * Docker Engine: 19.03.1
    * TigerVNC Viewer: 1.9.0
* コンテナ:
    * OS: Ubuntu 18.04.3 LTS

```text
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.5
BuildVersion:	18F132

$ docker version
Client: Docker Engine - Community
 Version:           19.03.1
 API version:       1.40
 Go version:        go1.12.5
 Git commit:        74b1e89
 Built:             Thu Jul 25 21:18:17 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.5
  Git commit:       74b1e89
  Built:            Thu Jul 25 21:17:52 2019
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          v1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc:
  Version:          1.0.0-rc8
  GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

$ docker image pull ubuntu:18.04
18.04: Pulling from library/ubuntu
Digest: sha256:d1d454df0f579c6be4d8161d227462d69e163a8ff9d20a847533989cf0c94d90
Status: Image is up to date for ubuntu:18.04
docker.io/library/ubuntu:18.04

$ docker container run --tty --rm ubuntu:18.04 cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.3 LTS"
```

## 4. `xeyes`を実行してみる

　シンプルなX11アプリとして目玉が表示される`xeyes`コマンドを実行してみます。
なお、`host$`はホストマシン、`docker$`はDockerコンテナ内での実行をそれぞれ示します。

### 4.1. 事前準備

　Dockerコンテナを起動し、必要なUbuntuパッケージをインストールします。なお、`xeyes`は`x11-apps`に含まれています。

```text
host$ docker container run --interactive --tty --rm --publish 5900:5900 ubuntu:18.04 /bin/bash

docker$ apt-get update
docker$ DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends xvfb x11vnc x11-apps
docker$ dpkg -l | grep -E "(xvfb|x11vnc|x11-apps)"
ii  x11-apps                   7.7+6ubuntu1             amd64        X applications
ii  x11vnc                     0.9.13-3                 amd64        VNC server to allow remote access to an existing X session
ii  x11vnc-data                0.9.13-3                 all          data files for x11vnc
ii  xvfb                       2:1.19.6-1ubuntu4.3      amd64        Virtual Framebuffer 'fake' X server
```

### 4.2. `xeyes`の起動

　`xvfb-run`コマンド経由で`xeyes`を実行します。
`xvfb-run`はデフォルトではディスプレイ番号`:99`で仮想ディスプレイを作成します。
また、デフォルトではPIDを含んだランダムな認証用ファイルを生成しますが、ここでは`/tmp/xvfb-run`に固定しています。

```text
docker$ xvfb-run --auth-file /tmp/xvfb-run -- xeyes &
```

### 4.3. VNCサーバの起動

　作成した仮想ディスプレイにアクセスするためのVNCサーバを起動します。
今回はVNCサーバの1つである`x11vnc`を使用しました。

```text
docker$ x11vnc -display :99 -auth /tmp/xvfb-run
```

### 4.4. VNCクライアントからアクセス

　起動したVNCサーバにVNCクライアント（ビューア）で接続します。今回はVNCクライアントの1つである「TigerVNC Viewer v1.9.0」を使用しました。
`x11vnc`は`5900/tcp`で接続を待機しています。
また、`docker container run`の`--publish`オプションでポートを転送しているため、`localhost`に対して接続を行います。

<img width="562" alt="connection.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58479/375ae73e-de9a-c268-660a-c943b5306c10.png">

　無事に接続でき、マウスカーソルの位置に応じて目玉が動くことを確認しました。

<img width="752" alt="connected.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58479/3bb5802e-68f9-bbad-7607-05854c603947.png">

## 5. 発展

　今回は単一のX11アプリを起動しましたが、Fluxboxなどウィンドウマネージャを起動することで、デスクトップ環境を実現することもできると思います。（試していません）

　また、Xの仮想ディスプレイはFFmpegで動画を撮影することもできるので、動画でテストの証憑（エビデンス）を記録するといった用途にも使えそうです。夢が広がりますね！

## 6. 参考

* [Xvfbで作った仮想ディスプレイにリモートデスクトップ接続する - いしだ日記](https://ishidamakot.hatenadiary.org/entry/20110717/1310890337)