Dockerで半クラウド開発生活を求めて挫折した話〜MacOS編


[Docker Advent Calendar](https://qiita.com/advent-calendar/2017/docker)の14日目の記事です。


# TL;DL

- 前提 : クラウドでの再現可能性と、ローカル開発の速度を両立したい
- 手段 : 開発サーバだけでなく、日常で利用するものすべてをコンテナ化すればどうか
- 結果 : Docker for Macだと実用化は難しい。やはり現段階ではブラウザベースで動作するものが汎用性が高い。
- 今後 : Docker for Ubuntuなどでも試してみたい

# はじめに

[Macに別れを告げて、クラウド中心の開発生活を始めるまで](https://qiita.com/cognitom/items/c489991a05f9abac748f)もそうだが、自分のまわりでもクラウドを開発の中心にする人が出始めている。
逆に自分はDockerを利用し、[可能な限りリモートに情報を残しながらローカルで開発](https://qiita.com/tomoyamachi/items/6862cd8ffe220689f6c0)している。
これらはともに「開発環境をどこからでも再現可能なものにしたい」という欲求から生まれていて、状況に応じて最適解は変わるだろう。

そして、あと2〜3年もすれば、世界中どこからも高速なインターネット接続環境が整い、人類はすべてクラウド上で仕事が完結するかもしれない。だが今ネットワークの弱い/ない状況は容易に想像できる。過渡期のいま、もっとも汎用性を高めるにはどうすればいいか。
そう、コンテナだ。

# 試してみたもの

開発で利用するものは、ブラウザ(Vivaldi, Chrome)、エディタ(Emacs)、ターミナル(iTerm2+tmux)なので、それが移行できればどこからでも開発できる。
今回、最も他環境への依存が多そうなGoogle Chromeを試した。
実行環境は以下のとおり。

- OS : macOS HighSierra 10.13.1
- Docker for Mac : 17.09.1-ce-mac42 (21090)
- Google Chrome : 63.0.3239.84 (Official Build)(64-bit)
	- ネイティブ、Docker環境ともに同じバージョン


# 手順
## 事前準備
[@jessのdockerfiles](https://github.com/jessfraz/dockerfiles)を利用する。Chrome以外にも主要なアプリケーションはすべてコンテナ化してある。

1. X Windows Systemを利用するため、MacOSX10.7以降は[XQuartz](https://www.xquartz.org/index.html)をインストール
2. 設定 > セキュリティ > ネットワークからの接続を許可する
![スクリーンショット 2017-12-11 4.51.22.png](https://qiita-image-store.s3.amazonaws.com/0/14275/7d830c2b-7046-2982-0d59-2eb0f3fa7a23.png "スクリーンショット 2017-12-11 4.51.22.png")


3. Xquartzを一度終了し、再度起動
4. プライベートIPからX Serverへのアクセスを許可する

```bash
$ brew cask install xquartz
$ open -a xquartz
$ xhost + $(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}')
```

## X Window ServerでChromeを起動

XQuartzのターミナル上で以下のコマンドを実行すると起動する。

```bash
# ホストマシンのプライベートIPを取得
export ip=$(ifconfig en0 | grep inet | awk '$1=="inet" {print $2}')

# X Serverにホストマシンからのアクセスを許可 ※ 最初の一度だけでよい
$ xhost + $ip

# seccompを取得 ※ 最初の一度だけでよい
$ wget https://raw.githubusercontent.com/jfrazelle/dotfiles/master/etc/docker/seccomp/chrome.json -O ~/chrome.json

$ docker run -it --rm \
 --net host \
 --cpuset-cpus 0 \
 --memory 512mb \
 -e DISPLAY=$ip:0 \
 -v /tmp/.X11-unix:/tmp/.X11-unix \
 -v $HOME/Downloads:/home/chrome/Downloads \
 -v $HOME/.config/google-chrome/:/data \
 -v /dev/shm:/dev/shm \
 --security-opt seccomp=$HOME/chrome.json \
 --name chrome \
 jess/chrome

```

なお、いまの設定だと以下のようなdbusとGPUについてのエラーが出る。
dbusについては、`brew install dbus` でdbusをインストールして、ソケットをマウントすればいいと思う。(今回、ベンチマークに関係ない部分なのでやってない)
また、2017年12月の段階でDocker for Macは、[GPUをサポートしていない](https://github.com/tensorflow/tensorflow/issues/6495)ようだ。つまりWebGLを利用しているサイトなどは動かない...

```
[1:22:1214/010258.471649:ERROR:bus.cc(395)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
ATTENTION: default value of option force_s3tc_enable overridden by environment.
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
[48:48:1214/010259.574081:ERROR:gl_context_glx.cc(232)] Couldn't make context current with X drawable.
[48:48:1214/010259.574154:ERROR:gpu_info_collector.cc(56)] gl::GLContext::MakeCurrent() failed
[48:48:1214/010259.574163:ERROR:gpu_info_collector.cc(119)] Could not create context for info collection.
[48:48:1214/010259.574175:ERROR:gpu_init.cc(53)] gpu::CollectGraphicsInfo failed (fatal).
[48:48:1214/010259.624488:ERROR:gpu_main.cc(164)] Exiting GPU process due to errors during initialization
[1:40:1214/010259.651146:ERROR:browser_gpu_channel_host_factory.cc(107)] Failed to launch GPU process.
[1:40:1214/010300.785085:ERROR:service_manager_context.cc(201)] Attempting to run unsupported native service: /opt/google/chrome/content_utility.service
```

  
## ベンチマーク


|| ネットワーク ||| 処理性能 |
|:---:|:---:|:---:|:---:|:---:|
| |ping|上り|下り|処理スコア||
|ネイティブ|16ms|38.73Mbps|100.39Mbps|86.406±11.650|
|コンテナ|26ms|12.36Mbps|16.24Mbps|66.537±9.8392|


### 処理性能の確認 : http://browserbench.org/JetStream/
#### ネイティブアプリ
![jetstream_native.png](https://qiita-image-store.s3.amazonaws.com/0/14275/a9afcbb2-e0d8-3b2c-3143-a00cf4c8ccc0.png "jetstream_native.png")

#### コンテナ経由
![jetstream_docker.png](https://qiita-image-store.s3.amazonaws.com/0/14275/a5f0ccd0-4a14-c66b-2ea6-190a73590187.png "jetstream_docker.png")

### ネットワークの確認 : http://beta.speedtest.net/

結果は明らかだったので、ネットワークの確認は3回しか行っていない。
いずれも上り速度が大きく落ちる。

#### ネイティブアプリ
![network_native.png](https://qiita-image-store.s3.amazonaws.com/0/14275/bd43682b-5c13-f34c-f4a5-807438956fd1.png "network_native.png")


#### コンテナ経由
![network_docker.png](https://qiita-image-store.s3.amazonaws.com/0/14275/3ad87f7c-9cf3-59f0-e2fe-fcb879358469.png "network_docker.png")


## 今の結論 

ネットワークまわりやX Window Serverについて詳しくないが、複数の環境を介すことにより、処理速度/ネットワーク速度ともに落ちた。
設定の問題もあるだろうが、macからの利用は、実用できるレベルのものではなかった。(というかGPUサポートない時点で、すでに結論は出ていた)

# おわりに

なお今回、処理とネットワークのことのみ書いており、コンテナから音声の出力を制御するための設定を入れていない。
Macの場合、[pulseaudio](https://hub.docker.com/r/jess/pulseaudio/)サーバを経由して音声を出すという方法があるが、それ以前にパフォーマンスが十分ではなかったので試していない。

UbuntuOSなどだと、GPUもサポートされるし、`--device /dev/snd` のようにdeviceを指定するだけでできるようなので、次回試す。