・Docker Desktop for Macでマウントしたボリュームはアクセス性能が低いと言われている。
・Docker 17.03から導入されたマウントオプションを使うことで改善できる。
そもそもなぜ遅いか
Linuxではホストとコンテナ間でVFSを基盤にしているのでファイル同期によるオーバーヘッドがない。
macOSではホストとコンテナで完全な一貫性を保つために著しいオーバーヘッドがある。
ファイル更新時の同期に時間がかかるだけで読み込みには時間がかからないということか。
チューニング方針
完全な一貫性を保つとするとオーバーヘッドで遅くなる。
一貫性が必要ないケースは多々ある。そのため一貫性を犠牲にすることで性能を上げる。
マウント設定
Dockerでマウント指定する際にマウント方法を指定することで一貫性を取るか性能を取るか決められる。
・consistent : ホストとコンテナで完全に同期する。
・cached : ホストを更新した時に遅延してコンテナに反映される
・delegated(委任) :コンテナの更新時に遅延してホストに反映される
-vオプションのコンテナpathの最後に:をつけて上記のパラメータを付与することで使用可能。
$ docker run -v /host/hoge:/container/hoge:cached sample
複数のボリュームで別の指定をすることも可能
$ docker run -v /host/1:/container/1:cached -v /host/2:/container/2:delegated sample
delegated
一番性能が上がる。ホストは変更せず、コンテナ側から一方的に変更するものに使用するのが良さそう。
コンテナのファイル状態を正とし、コンテナを修正してもホストに遅れて反映される。
破損してもokな一時的なファイルや再生成可能なビルド物に向いている。
delegatedでマウントしている場所をcachedやconsistentでマウントするとその場所はそれぞれの指定に従う。
ホスト側で変更をしても、コンテナ側の同期によってその変更が消える可能性がある。
cached
ホストを正にする。ホストの書き込みはコンテナにすぐに同期されるが、コンテナの変更は遅延してホストに同期される。
cachedでマウントしている箇所をconsistentでマウントするとconsistentの挙動になる。
consistent
ホストとコンテナが完全に同期する。
デフォルトでこの指定。
パフォーマンス測定
Laravelプロジェクトをマウントしマウント設定を変えてパフォーマンスを計測する。
まずはローカルで直接artisan serveを起動した状態。1秒で29リクエスト捌ける。
$ ab -c 5 -n 25 http://127.0.0.1:8000/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 127.0.0.1 (be patient).....done
Server Software:
Server Hostname: 127.0.0.1
Server Port: 8000
Document Path: /
Document Length: 17473 bytes
Concurrency Level: 5
Time taken for tests: 0.855 seconds
Complete requests: 25
Failed requests: 0
Total transferred: 465475 bytes
HTML transferred: 436825 bytes
Requests per second: 29.22 [#/sec] (mean)
Time per request: 171.097 [ms] (mean)
Time per request: 34.219 [ms] (mean, across all concurrent requests)
Transfer rate: 531.35 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 43 148 35.2 161 179
Waiting: 41 147 35.4 159 177
Total: 43 149 35.2 161 179
Percentage of the requests served within a certain time (ms)
50% 161
66% 162
75% 164
80% 166
90% 172
95% 174
98% 179
99% 179
100% 179 (longest request)
コンテナ側に/appでマウントすると、
$ tree -L 2
.
├── Dockerfile
└── laravel
├── README.md
├── app
├── artisan
├── bootstrap
├── composer.json
├── composer.lock
├── config
├── database
├── docker-compose.yml
├── package.json
├── phpunit.xml
├── public
├── resources
├── routes
├── server.php
├── storage
├── tests
├── vendor
└── webpack.mix.js
FROM centos:centos8
RUN dnf module install -y php:7.4
WORKDIR /app
CMD [ "php", "artisan", "serve", "--port=80", "--host=0.0.0.0" ]
マウントする
$ docker run -it --rm -v $(pwd)/laravel:/app/ -p 8080:80 ro_test
この状態で5人が5回、合計25アクセスした時のパフォーマンス
$ ab -c 5 -n 25 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient).....done
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 17473 bytes
Concurrency Level: 5
Time taken for tests: 8.982 seconds
Complete requests: 25
Failed requests: 0
Total transferred: 465475 bytes
HTML transferred: 436825 bytes
Requests per second: 2.78 [#/sec] (mean)
Time per request: 1796.408 [ms] (mean)
Time per request: 359.282 [ms] (mean, across all concurrent requests)
Transfer rate: 50.61 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 373 1578 436.6 1755 1863
Waiting: 373 1578 436.7 1755 1862
Total: 373 1578 436.6 1755 1863
Percentage of the requests served within a certain time (ms)
50% 1752
66% 1769
75% 1778
80% 1804
90% 1810
95% 1825
98% 1863
99% 1863
100% 1863 (longest request)
パフォーマンス cached
cachedなので若干パフォーマンスが上がるはず
$ docker run -it --rm -v $(pwd)/laravel:/app/:cached -p 8080:80 ro_test
計測。あまり変わらない。。。
$ ab -c 5 -n 25 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient).....done
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 17473 bytes
Concurrency Level: 5
Time taken for tests: 8.948 seconds
Complete requests: 25
Failed requests: 0
Total transferred: 465475 bytes
HTML transferred: 436825 bytes
Requests per second: 2.79 [#/sec] (mean)
Time per request: 1789.501 [ms] (mean)
Time per request: 357.900 [ms] (mean, across all concurrent requests)
Transfer rate: 50.80 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 353 1571 435.7 1750 1813
Waiting: 353 1571 435.8 1749 1813
Total: 353 1571 435.7 1750 1814
Percentage of the requests served within a certain time (ms)
50% 1749
66% 1762
75% 1777
80% 1791
90% 1795
95% 1812
98% 1814
99% 1814
100% 1814 (longest request)
パフォーマンス delegated
$ docker run -it --rm -v $(pwd)/laravel:/app/:delegated -p 8080:80 ro_test
計測。これもあんまり変わらない。むしろ遅くなっている。
$ ab -c 5 -n 25 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient).....done
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 17473 bytes
Concurrency Level: 5
Time taken for tests: 9.187 seconds
Complete requests: 25
Failed requests: 0
Total transferred: 465475 bytes
HTML transferred: 436825 bytes
Requests per second: 2.72 [#/sec] (mean)
Time per request: 1837.459 [ms] (mean)
Time per request: 367.492 [ms] (mean, across all concurrent requests)
Transfer rate: 49.48 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 391 1582 403.0 1740 1843
Waiting: 391 1581 402.9 1739 1843
Total: 391 1582 403.0 1740 1843
Percentage of the requests served within a certain time (ms)
50% 1739
66% 1753
75% 1765
80% 1770
90% 1841
95% 1842
98% 1843
99% 1843
100% 1843 (longest request)
コードをコンテナの中に入れる
FROM centos:centos8
RUN dnf module install -y php:7.4
COPY ./laravel /app
WORKDIR /app
CMD ["php", "artisan", "serve", "--host=0.0.0.0"]
計測。コンテナ使う上ではこれが一番速い。秒間15リクエスト捌ける。
ab -c 5 -n 25 http://localhost:8080/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient).....done
Server Software:
Server Hostname: localhost
Server Port: 8080
Document Path: /
Document Length: 17473 bytes
Concurrency Level: 5
Time taken for tests: 1.682 seconds
Complete requests: 25
Failed requests: 0
Total transferred: 465475 bytes
HTML transferred: 436825 bytes
Requests per second: 14.86 [#/sec] (mean)
Time per request: 336.380 [ms] (mean)
Time per request: 67.276 [ms] (mean, across all concurrent requests)
Transfer rate: 270.27 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 94 295 70.8 316 355
Waiting: 93 294 71.0 315 354
Total: 94 295 70.7 316 355
Percentage of the requests served within a certain time (ms)
50% 315
66% 328
75% 331
80% 333
90% 345
95% 348
98% 355
99% 355
100% 355 (longest request)
書き込みパフォーマンス
ファイル書き込み時のパフォーマンスをチェックする
ローカルで計測した場合
$ time (for i in $(seq 1 10000);do echo $i >> a.txt; done)
========================
Program : ( for i in $(seq 1 10000); do; echo $i >> a.txt; done; )
CPU : 88%
user : 0.110s
system : 0.550s
total : 0.746s
========================
consistentでマウントした場合。
コンテナで書き込むと0.220s。とても遅い。
ホストで書き込むと0.119s。
同じくらいかかると思ったけどコンテナの方が遅い。
$ docker run -it --rm -v $(pwd)/fuga:/fuga centos:centos8
[root@29e3d05941ce fuga]# time (for i in $(seq 1 10000);do echo $i >> a.txt; done)
real 0m11.249s
user 0m0.220s
sys 0m0.700s
$ time (for i in $(seq 1 10000);do echo $i >> b.txt; done)
========================
Program : ( for i in $(seq 1 10000); do; echo $i >> b.txt; done; )
CPU : 88%
user : 0.119s
system : 0.608s
total : 0.817s
========================
書き込みパフォーマンス cached
$ docker run -it --rm -v $(pwd)/fuga:/fuga:cached centos:centos8
[root@53b5e0d31c60 fuga]# time (for i in $(seq 1 10000);do echo $i >> aa.txt; done)
real 0m13.132s
user 0m0.271s
sys 0m0.804s
↓ホスト側。consistentの時より若干早くなっている
time (for i in $(seq 1 10000);do echo $i >> ab.txt; done)
========================
Program : ( for i in $(seq 1 10000); do; echo $i >> ab.txt; done; )
CPU : 89%
user : 0.119s
system : 0.597s
total : 0.800s
========================
書き込みパフォーマンス delegated
cachedより速くなってる。
$ docker run -it --rm -v $(pwd)/fuga:/fuga:delegated centos:centos8
[root@e8334765081e fuga]# time (for i in $(seq 1 10000);do echo $i >> ddd.txt; done)
real 0m11.714s
user 0m0.191s
sys 0m0.780s
↓ホスト側。cchedより遅い・・・?
$ time (for i in $(seq 1 10000);do echo $i >> affff.txt; done)
========================
Program : ( for i in $(seq 1 10000); do; echo $i >> affff.txt; done; )
CPU : 87%
user : 0.123s
system : 0.616s
total : 0.849s
========================