19
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WHITEPLUSAdvent Calendar 2016

Day 24

docker-syncを使わないホスト・コンテナ間での爆速ファイル同期

Last updated at Posted at 2016-12-23

#追記 20170407 Docker for Macでconsistencyを指定することでパフォーマンスを改善できるようになりました。

unisonを使わなくても本体の機能である程度解決できるようになりました。
下記の計測してるので参照ください。
http://qiita.com/kai-zoa/items/5f38909d37e0e4e36a28

#元記事
この記事はWHITEPLUS Advent Calendar 2016 24日目になります。

開発環境整備担当兼クリーニング師の kai-zoa です。

20日目に書いたDocker for Macのファイル共有が遅いので計測してみるでdocker-for-mac公式は問題を認識しているが優先度低いという旨のコメントを頂いたので、なにかしら対策を講じたい気持ちになり調査しました。

すでにdocker-syncを使う方法は他の方が紹介されているので、今回は使わない方法について書きたいと思います。

実際に開発環境に組み込んでデザイナー・エンジニアの両チームに共有するのにあらかじめrubyを入れてもらったり、gemを使えるようにしてもらうのが面倒くさい方にオススメです。(というのが私の都合です)

環境はmacOSです。

#unisonを使います

いきなりですが、これが答えです。

docker-syncでも使われていますが、同じようにunisonを使ってホストとコンテナのファイルシステムを相互同期します。

DockerHubにalpineベースのシンプルなunisonサーバーのDockerイメージがあったので参考にしました。
onnimonni/unison

このようにunisonサーバーをデータコンテナーにして、同期するディレクトリはアプリケーション側のボリュームにマウントします。

Screen Shot 2016-12-24 at 3.47.47 AM.png

docker-composeの定義はこんな感じです。

docker-compose.yml
version: '2'

services:
  data:
    image: whiteplus/unison
    container_name: piyo_data
    volumes:
      - /var/www/piyo
    ports:
      - "5000:5000"
    environment:
      - UNISON_DIR=/var/www/piyo
  web:
    container_name: piyo_web
    build: .
    depends_on:
      - data
    volumes_from:
      - data
    ports:
      - "80:80"
      - "443:443"
    environment:
      - NGINX_PATH_PREFIX=/var/www/piyo

※ データコンテナー側にinotify-toolsを入れたかったのでonnimonni/unisonに手を入れてwhiteplus/unisonにしてます。

全ソースはこちら
github.com/WHITEPLUS/advent-calendar2016-docker-unison-example

#動作確認

起動します。

$ docker-compose up -d

起動直後はプロジェクトのファイルを同期してないのでwebにアクセスすると404になります。

$ open http://localhost
207bc9ba-c3e3-4e30-9acc-c68fb75eb666.png

##ホストのファイルをデータコンテナに同期する
それではunisonクライアントをインストールして、./webappのソースをデータコンテナに同期してみます。

$ brew install unison
$ unison ./webapp socket://127.0.0.1:5000/ -auto -batch
Contacting server...
Connected
〜
  Waiting for changes from server
Reconciling changes
dir      ---->            html
Propagating updates
〜
Synchronization complete at 21:12:35  (2 items transferred, 0 skipped, 0 failed)

$ open http://localhost #開いてみる
3dbec3ee-5c0a-4b9f-a489-f4ea29eabcaf.png

WAO! ちゃんと表示されました

##データコンテナからファイルを編集して同期する

それでは逆にデータコンテナからファイルを編集して同期してみましょう

$ docker exec -it piyo_data sh # データコンテナに入る
$ cd /var/www/piyo/html/
$ echo PIYOPIYO > index.html #データコンテナからファイルの内容を変更
$ exit

$ unison ./webapp socket://127.0.0.1:5000/ -auto -batch #同期
Contacting server...
Connected
〜
Looking for changes
  Waiting for changes from server
Reconciling changes
         <---- changed    html/index.html
Propagating updates
〜
Synchronization complete at 21:21:53  (1 item transferred, 0 skipped, 0 failed)

$ cat ./webapp/html/index.html #変更がホストに反映されてることを確認する
PIYOPIYO

WAO! うまくいきました

#ファイル変更を監視して同期する

ここまでできたら、ホストとコンテナでお互いのファイル変更イベントを検知して、unisonを動かすようにすれば完璧ですね。

そこでお互いのinotifyイベントを監視して、ホスト側にログ出力し、tailからxargsでunisonに繋ぐスクリプトを書いてみました。(githubの方にもコミットしています)

unison-fsmonitorをmacOSに入れればこんなもの必要ないかもしれないですがまだ試してません

sync.sh
#! /usr/bin/env bash

LOCAL_DIR=./webapp
REMOTE_DIR=/var/www/piyo
REMOTE_CID=piyo_data

recv_local() {
  while read -r event; do
    test -n "${event}" && \
    echo "LOCAL: ${event}" >> events.log
  done
}

recv_remote() {
  while read -r event; do
    event=$(echo -n $event \
    | grep -E '(CREATE|MOVE|MOVED_TO|MOVED_FROM|MODIFY|ATTRIB|DELETE|DELETE_SELF)[,:]' \
    | sed -e 's/^[A-Z,_]*://g' \
    | tr -d '\n')
    test -n "${event}" && \
    echo "REMOTE: ${event}" >> events.log
  done
}

UNISON="unison ${LOCAL_DIR} socket://127.0.0.1:5000/ -auto -batch"

${UNISON}

rm -f events.log
touch events.log

fswatch ${LOCAL_DIR} 2>&1 | recv_local &
CHILDREN=$!

docker exec -it ${REMOTE_CID} inotifywait -m -r --format '%e:%w%f' ${REMOTE_DIR} 2>&1 | recv_remote &
CHILDREN="${CHILDREN} $!"

trap "kill -KILL ${CHILDREN} > /dev/null 2>&1" INT TERM

tail -f ./events.log | xargs -I{} ${UNISON}

実行するとホストとコンテナ双方のファイル監視と同期をし続けてくれます。

$ ./sync.sh
〜

#積み残し

上記スクリプトだとunisonが同期した結果のファイル変更イベントを検知してunisonが起動するという無駄な動きもしてしまうので改良の余地があるなと思いました。

これ以上、並行処理でなんやかんややるならGoで書きたいですね‥

その前にfsmonitorを使った場合の動作確認をしよう!

#明日
exmeatのmeatの話ですっ

#ホワイトプラスではエンジニアを募集しています
ホワイトプラスでは、新しい技術にどんどん挑戦したい!という技術で事業に貢献したいエンジニアを募集しております。!

19
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?