MacおよびWinにおけるDocker環境のベンチマーク結果まとめ(2017-10-23現在)

# 2018-04-07 追記

Docker for Mac の 18.03.0-ce の新機能として、NFS Volume Sharing というのが追加されました。これにより、ローカルファイルシステムのマウント性能が大幅に改善されたので、再度ベンチマークを取っていますので、そちらの結果も参照してみてください。

- [Docker for Mac の NFS Volume sharing のベンチマーク結果(2018-03-29現在)](https://qiita.com/kunit/items/36d9e5fa710ad26f8010)

# はじめに

2017/10/21に開催された [Fukuoka.php Vol.24](https://fukuokaphp.connpass.com/event/68105/) において、「Docker for Mac/Winってどうなの？」というタイトルで発表させていただきました。
その中で Mac および Win での Docker の動作環境によるベンチマーク結果をデモを行いました。

- Fukuoka.php Vol.24 の発表資料
  - https://speakerdeck.com/kunit/number-fukuokaphp-docker-for-mac-and-win

その結果をあらためてまとめ直したのがこの記事です。

# 測定内容1 - symfony-3.0 のベンチマーク結果

[@kenji_s](https://twitter.com/kenji_s) さんが公開されている各フレームワークのベンチマークを測定するためのセットを使用させていただいて、その中で「symfony-3.0」のベンチマークを使って、環境によってどのような結果の違いがでるかというのを比較しました。

- https://github.com/kenjis/php-framework-benchmark

なお、kenji_s さんが配布されているリポジトリの内容を mac 上に git clone し、それを各環境にマウントして使用するという形をとりました。

これは、Docker for Mac がローカルマウントしたボリュームに対する読み書きが極端に遅いということをベンチマーク結果に反映させるためです。

# 測定内容2 - dd コマンドの実行スピード

 Docker for Mac のローカルマウントしたボリュームが極端に遅いという 記事を [@hanhan1978](https://twitter.com/hanhan1978) さんがブログで公開されてます。

   - [Docker for Macのmount遅い問題まとめ](https://blog.hanhans.net/2017/05/23/docker-for-mac-slow/)

この記事によると、以下のコマンドの実行速度が環境によって極端に変わってくるということなので、その時間を測定しました。

```
time dd if=/dev/zero of=test bs=1k count=100000
```

※ 1kb を 100万回書き込む(100MBを書き込む)形となる

# 測定環境

測定した環境は以下のもの。

- Vagrant + Virtualbox
  - Virtualbox 上の CentOS 6.9 の上で、Apache 2.2 + PHP 5.6 を動作させる
  - Mac 上のローカルディスクを nfs マウントして使用する
- Vagrant + Virtualbox + CoreOS
  - https://github.com/coreos/coreos-vagrant
  - Virtualbox 上の CoreOS の上で、Docker環境を作成
  - Docker コンテナとして CentOS 6.9 + Apache 2.2 + PHP 5.6 を動作させる
  - Mac 上のローカルディスクをVirtualbox のCoreOS上に nfs マウントし、それを更にDockerコンテナにマウントする
- Docker for Mac（通常)
  - Macにインストールした Docker for Mac を使用し、Mac上から直接 CentOS 6.9 + Apache 2.2 + PHP 5.6 を動作させる
  - Mac 上のローカルディスクをDockerコンテナに普通にマウントする
- Docker for Mac（cached)
  - Macにインストールした Docker for Mac を使用し、Mac上から直接 CentOS 6.9 + Apache 2.2 + PHP 5.6 を動作させる
  - Mac 上のローカルディスクをDockerコンテナにcachedオプション付きでマウントする
- Docker for Mac（docker-sync)
  - Macにインストールした Docker for Mac を使用し、Mac上から直接 CentOS 6.9 + Apache 2.2 + PHP 5.6 を動作させる
  - Mac 上に [docker-sync](http://docker-sync.io/) を gem install し、それを使って、マウントするためのデータボリュームを作成する
  - docker-sync で作成したデータボリュームをDockerコンテナにマウントする
  - 実際の同期には rsync を使っている
- Docker for Win
  - Windows 10 Proにインストールした Docker for Win を使用し、Win上から直接 CentOS 6.9 + Apache 2.2 + PHP 5.6 を動作させる
  - Win 上のローカルディスクをDockerコンテナに普通にマウントする

PHPの実行環境としては以下のもので揃えています。

- CentOS 6.9
- yum で install した Apache 2.2
- remi リポジトリを使用して、yum で install した PHP 5.6

使用した Docker for Mac/Win は以下のバージョン。

- Docker for Mac
  - Docker CE edge Version 17.09.0-ce-mac24(19605)
- Docker for Win
  - Docker CE edge Version 17.09.0-ce-win34(13622)

# 測定結果

## symfony-3.0 のベンチマーク結果

|OS|環境|requests per second|
|:----|:----|:----|
|Mac|Vagrant + Virtualbox         |90.59|
|Mac|Vagrant + Virtualbox + CoreOS Docker環境|85.78|
|Mac|Docker for Mac(通常)          |38.10|
|Mac|Docker for Mac(cached)       |83.04|
|Mac|Docker for Mac(docker-sync)  |108.08|
|Win10Pro|Docker for Win          |109.42|

Vagrant + Virtualbox の組み合わせを基準と考えた場合、

- Vagrant + Virtualbox + CoreOS Docker環境はほぼ変わらない性能がでる
- Docker for Mac の通常のマウント方法はかなり足をひっぱり、性能に対する影響がでかい
- Docker for Mac の cached 方式のマウント方法はかなり頑張っていて、遜色ない性能がでている
- Docker for Mac の docker-sync 方式のマウント方法はかなり性能がでている
  - Vagrant環境の NFS を使ったマウントは、それはそれで前々から性能に文句がでているものなので、それよりは rsync を使っている docker-sync のほうが性能がでたということになる
- Docker for Win はかなり頑張っていて、docker-sync を使ったものと同じくらいの性能を発揮する

## dd コマンドの実行スピード

|環境 | real | user | sys |
|:--------------------|:-----|:-----|:----|
|Vagrant + Virtualbox         | 0m0.238s | 0m0.003s | 0m0.231s |
|Vagrant + Virtualbox + CoreOS Docker環境| 0m0.955s | 0m0.007s | 0m0.179s |
|Docker for Mac(通常)          | 0m20.227s | 0m0.150s | 0m2.770s |
|Docker for Mac(cached) | 0m13.480s | 0m0.090s | 0m0.520s |
|Docker for Mac(docker-sync) | 0m0.292s | 0m0.000s | 0m0.290s |
|Docker for Win              | 0m0.369s | 0m0.030s | 0m0.140s |

Vagrant + Virtualbox の組み合わせ(0.238秒)を基準と考えた場合、

- Vagrant + Virtualbox + CoreOS Docker環境は、少し書き込みスピードに影響がでている(1秒弱)
- Docker for Mac の通常のマウント方法は、@hanhan1978 さんのブログの記事通り、書き込み性能にかなり問題があり、20秒もかかってしまっている
- Docker for Mac の cached 方式のマウント方法は、通常マウントよりは少しマシになっているが、それでもかなり遅い(13秒強)
- Docker for Mac の docker-sync 方式のマウント方法は、素の Virtualbox の時間とほぼ変わらない時間で実行が完了する(0.3秒弱)
- Docker for Win は、素の Virtualbox の時間とほぼ変わらない時間で実行が完了する(0.369秒)

# まとめ

現時点での Mac および Windows のDocker環境に関しては以下のような形になると思います。

- Mac でDocker環境を作るならば、Docker for Mac + docker-sync を試してみて、それでも支障がでるならば、Virtualbox を利用する Docker toolbox か、CoreOS ベースのDocker環境を選ぶのがいいと思う
- Docker for Windows は、性能面での心配はほぼない。Hyper-V を ON できる環境であれば使えるので、積極的に使っていくのがいいと思う

# 使用したファイルたち

## Dockerfile

各Docker環境で使用した Dockerfile

```
FROM centos:6.9

RUN yum -y update \
  && yum -y install epel-release \
  && rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm \
  && yum -y install httpd httpd-devel \
  && yum install -y --enablerepo=remi,remi-php56 php php-cli php-pear php-devel php-mbstring php-mcrypt php-pdo php-mysqlnd php-gd php-xml php-zip php-opcache php-pecl-apcu php-pecl-xdebug

WORKDIR /var/www/html

EXPOSE 80

CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
```

## docker-compose.yml

以下の環境で使用した docker-compose 用の設定ファイル

- Vagrant + Virtualbox + CoreOS Docker環境
- Docker for Mac(通常)
- Docker for Win

```
version: '3.3'
services:
    db:
        image: mysql:5.7
        hostname: db
        container_name: db
        environment:
            - MYSQL_ROOT_PASSWORD=root
        volumes:
            - ./data:/var/lib/mysql
        ports:
            - "3306:3306"

    web:
        build: .
        image: centos69-apache-php
        hostname: web
        container_name: web
        volumes:
            - ../htdocs:/var/www/html
        ports:
            - "8080:80"
        depends_on:
            - db
```

## docker-compose-cached.yml

Docker for Mac(cached)で使用した、docker-compose 用の設定ファイル

```
version: '3.3'
services:
    db:
        image: mysql:5.7
        hostname: db
        container_name: db
        environment:
            - MYSQL_ROOT_PASSWORD=root
        volumes:
            - ./data:/var/lib/mysql
        ports:
            - "3306:3306"

    web:
        build: .
        image: centos69-apache-php
        hostname: web
        container_name: web
        volumes:
            - ../htdocs:/var/www/html:cached
        ports:
            - "8080:80"
        depends_on:
            - db
```

## docker-sync.yml

Docker for Mac(docker-sync)で使用した、docker-sync 用の設定ファイル

```
version: '2'
syncs:
  htdocs-sync:
    src: '../htdocs'
```

## docker-compose-with-docker-sync.yml

Docker for Mac(docker-sync)で使用した、docker-compose 用の設定ファイル

```
version: '3.3'
services:
    db:
        image: mysql:5.7
        hostname: db
        container_name: db
        environment:
            - MYSQL_ROOT_PASSWORD=root
        volumes:
            - ./data:/var/lib/mysql
        ports:
            - "3306:3306"

    web:
        build: .
        image: centos69-apache-php
        hostname: web
        container_name: web
        volumes:
            - htdocs-sync:/var/www/html:nocopy
        ports:
            - "8080:80"
        depends_on:
            - db

volumes:
    htdocs-sync:
        external: true
```