Dockerにdocker-syncを導入して遅い問題を解決する
はじめに
どうもこんちゃんです。最近開発環境にDockerを使用するようになって、いざ使ってみるとdocker for Macだと同期がクソ遅い問題(ページのロードで20秒)が発生してイライラしてたのが、docker-syncの導入で遅い問題が解決されたのでそれについて話していきたいと思います。
docker sync
docker sync はホスト側のファイルを rsync
や unison
もしくは native_osx
を使って転送するという仕組みを導入しています。なので、重たくなる原因でもあったホスト側のディレクトリをマウントしていません。
github.com
いざ導入
インストール
公式によるとこれだけ
gem install docker-sync
docker syncの設定を追加する
下記の docker-compose.yml
を例に設定を進めていきます。
docker-compose.yml
version: '2' services: app: image: test volumes: - $DEV_DIR : /var/dev command: yarn build:dev
まず、docker-sync.yml
というファイルを追加します。
わかりやすくするためにdocker-syncの設定は docker-sync.yml
書いていきますが、docker-compose.yml
自体に書いていくこともできます。
僕の周りではDockerをLinux仮想環境を自分で用意してその中で動かしている人も一定数いたため、
既存の人は既存のまま使えるようにdocker-compose.yml
はそのままにDockerの上書き用のymlである docker-compose-dev.yml
に設定を追加していきます。
docker-sync.yml
version: '2' syncs: sync-volume: src: $DEV_DIR sync_strategy: native_osx sync_excludes: [ '.git', '.idea', '.vagrant' ]
docker-sync.yml
では、まず src
でホスト側のディレクトリを指定します。
sync_strategy
では同期方法を選択できます。今回は native_osx
という方法を選択しました。 native_osx
はUnison
とDocker用のファイル共有システムである OSXFS
の組み合わせです。
sync_excludes
では同期しないファイルもしくはファイル形式を配列で渡すことができます。指定されたファイルもしくはファイル形式は同期対象外になります。
* sync-volume
は任意の名前で構いませんが、ここでの名前がDockerの名前付きvolumeとして作られます。
docker-compose-dev.yml
version: '2' volumes: sync-volume: external: true services: app: volumes: - sync-volume:/var/dev
docker-compose-dev.yml
では、docker-sync側で作るvolume
を external
として宣言し、それを sync-volume:/var/test
としてマウントするように設定しています。
設定は以上になります。
とりあえず動かしてみようぜ
設定追加できたらとりあえず動かしてみましょう。
docker-sync-stack start
で動きます。
内部的にやっていることはdocker-syncを起動してupしてるだけらしい
内部的にはこういうこと
docker-sync start docker-compose -f docker-compose.yml -f docker-compose-dev.yml up
2.2 sync stack commands · EugenMayer/docker-sync Wiki · GitHub
ここで指定している -f
オプションが先ほど言っていた上書き設定のオプションで、ここでファイルを複数指定すると指定された順番に設定を反映します。
なので docker-compose.yml
-> docker-compose-dev.yml
という順番に設定を反映していきます。
同じ設定があった場合は後に反映された設定が前の設定を上書きされるようになります 。
このあとこの上書きした項目の1つが原因でえらいことになる
動かしてみると...
実際に動かしてみると 20秒ぐらいだったページのロードが1秒ぐらい になりました。やっほー!めっちゃ快適やんけーって思いながら開発を進めていると.....
ファイルの変更が反映されてないぞ という問題が発生しました。実は先ほど上書きした設定の中に問題の原因が隠れていました。
それは volumeの設定です 。
下記のissueコメントなどを参考に話をしていくと、どうやらupしたymlが複数指定されていると volume
は上書きされないっぽい。
Your issue is, that you think you can override volume defintions, but you cannot. So ${SYMFONY_APP_PATH}:/var/www/symfony stays in charge and supersync-sync:/var/www/symfony:nocopy never gets used.
volumeオーバーライドされない問題を解決しよう
ここでvolumeをオーバーライドされない問題を解決する手段は2つあります。
そもそも、ymlの設定を複数に渡ってせずに docker-compose.yml
に統一してしまう。もしくは、 volumes
の設定を他の設定ファイルに切り出すことです。
今回は後者の volumes
の設定を切り出すことを選択しました。(先ほどにもあげたようにdocker-syncを使わなくても良いユーザも一定数いるため)
Dockerにはデフォルト上書きしてくれるymlファイルがある
では、volumes
の設定をどこに書くのかというと、Dockerではデフォルトで2つのファイルを読みます。
それは docker-compose.yml
とdocker-compose.override.yml
です。 今回はこの docker-compose.override.yml
に volumes
を切り出しました。
docker-compose.override.yml
version: '2' services: app: volumes: - sync-volume:/var/dev
これでdocker-syncを使わない人と使う人で特に意識することなく利用できそうです。
サービスの拡張と Compose ファイル — Docker-docs-ja 17.06.Beta ドキュメント
追記(2018/7/5)
volumeオーバーライドされない問題はどうやら解決されたらしいです。(下記issue参照)
Docker Compose 1.17 fixed volumes override 🕊 · Issue #507 · EugenMayer/docker-sync · GitHub
しかし、同時に同期が安定的でないというissueもあります。 僕の方でも同期がうまくいかないという場面が度々見受けられました。 とりあえずこの問題が解決次第また記事に追加していこうと思います。
Synchronization stops. · Issue #517 · EugenMayer/docker-sync · GitHub