Dockerにdocker-syncを導入して遅い問題を解決する

はじめに

どうもこんちゃんです。最近開発環境にDockerを使用するようになって、いざ使ってみるとdocker for Macだと同期がクソ遅い問題(ページのロードで20秒)が発生してイライラしてたのが、docker-syncの導入で遅い問題が解決されたのでそれについて話していきたいと思います。
 

docker sync

docker sync はホスト側のファイルを rsyncunison もしくは 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_osxUnison と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側で作るvolumeexternal として宣言し、それを 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.
 

github.com  

volumeオーバーライドされない問題を解決しよう

ここでvolumeをオーバーライドされない問題を解決する手段は2つあります。
そもそも、ymlの設定を複数に渡ってせずに docker-compose.yml に統一してしまう。もしくは、 volumes の設定を他の設定ファイルに切り出すことです。 今回は後者の volumes の設定を切り出すことを選択しました。(先ほどにもあげたようにdocker-syncを使わなくても良いユーザも一定数いるため)  

Dockerにはデフォルト上書きしてくれるymlファイルがある

では、volumes の設定をどこに書くのかというと、Dockerではデフォルトで2つのファイルを読みます。 それは docker-compose.ymldocker-compose.override.yml です。 今回はこの docker-compose.override.ymlvolumes を切り出しました。  
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