docker for Macでvolumeのcachedを使ってIO性能を向上させる

概要

現在、会社の開発環境でdocker for mac/windowsを採用している。
開発環境なので、都度コンテナにログインはせずに、docker-composeを使用して、ローカルのGithubリポジトリをマウントすることで、開発環境としている。

問題

フロントエンドのコンテナでyarn buildすると明らかにローカルで実施したときよりも遅い。
マウントしているから仕方がないとはいえ、体感でも倍以上のビルド時間がかかっているように思われた。

対策

色々調べていたら、先日弊社の開発ランチにも来られたコネヒトさんのブログがあった。

開発環境改善としてDockerを導入した話

Volumeにcachedオプションを採用しているとのことだった。

volumeオプション(consistent/cached/delegated)

https://docs.docker.com/docker-for-mac/osxfs-caching/#performance-implications-of-host-container-file-system-consistency

デフォルトはホストとコンテナの変更点の差分を小さくするためにconsisutentになっているようだ。
cachedはホストの更新がコンテナへ反映される時間の遅延を許容し、delegatedはコンテナの更新をホストに反映されるまでの時間の遅延を許容するらしい。
cachedとdelegatedのどちらを使用すべきか判断が難しいが、cachedを設定している記事が多いのでまずはcahedで様子見してみることにした。

コード

コードとしては、docker runのvolumeにcachedを付与するか、docker-composeに付与する。

docker run

docker run -dti -v $(pwd):/var/www/:cached centos bash

docker-compose

 volume:
   - ../../dir1:/var/www/repos:cached

計測結果

BEFORE

root@78d7d3c19461:/var/www/repos# time yarn build
yarn run v1.9.4
(node:100) ExperimentalWarning: The fs.promises API is experimental
$ node scripts/build.js
(node:111) ExperimentalWarning: The fs.promises API is experimental
Creating an optimized production build...
Starting type checking and linting service...
Using 1 worker with 2048MB memory limit
ts-loader: Using typescript@3.0.3 and /var/www/repos/tsconfig.json
No valid rules have been specified for JavaScript files
Compiled successfully.

File sizes after gzip:

  178.96 KB  build/static/js/main.74396754.js
  342 B      build/static/css/main.bbe4c04e.css

The project was built assuming it is hosted at ./.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.

Find out more about deployment here:

  http://bit.ly/2vY88Kr

Done in 91.87s.

real    1m33.245s
user    0m42.370s
sys     0m19.600s

だいたい1分半(90秒)くらいビルドにかかっている。

AFTER

root@e9b7171db6f7:/var/www/repos# time yarn build
yarn run v1.9.4
(node:99) ExperimentalWarning: The fs.promises API is experimental
$ node scripts/build.js
(node:110) ExperimentalWarning: The fs.promises API is experimental
Creating an optimized production build...
Starting type checking and linting service...
Using 1 worker with 2048MB memory limit
ts-loader: Using typescript@3.0.3 and /var/www/repos/tsconfig.json
No valid rules have been specified for JavaScript files
Compiled successfully.

File sizes after gzip:

  178.96 KB  build/static/js/main.74396754.js
  342 B      build/static/css/main.bbe4c04e.css

The project was built assuming it is hosted at ./.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.

Find out more about deployment here:

  http://bit.ly/2vY88Kr

Done in 48.93s.

real    0m50.025s
user    0m34.680s
sys     0m12.300s

なんと43秒減で約半分までビルド時間が短くなった。

感想

これでどの程度影響があるかは不明だが、おそらく少しはマシになったのではないかと思う。
ただ、ホストへの更新が遅延するとのことなので、その辺は開発者の方の意見を吸い上げつつ、調整をしていきたい。