Closed16

rubocop-daemonはdocker-compose環境で動くか?

docker-compsoe.ymlにて

  rubocop_daemon:
    build:
      context: ./backend
    command: bundle exec rubocop-daemon start --no-daemon
    volumes:
      - /app/.bundle
    logging:
      driver: none

とした上でdocker-compose exec rubocop_daemon bundle exec rubocop-daemon execとすればひとまず動く。
vscodeならこれをshellスクリプトにでもしてPATH通せばよいはず。

※なおディレクトリ構成は以下

/project-root/
  - docker-compose.yml
  - backend/
      - Gemfile

しかしこれでは起動オーバーヘッドが大きく、「daemonにしなくてもdocker-compose execでrubocop動かせば良くない?」となる。

やはりrubocop-daemon-wrapper版を動かしたい。

shellscriptは色々やっていてよくわからんのだが、要するに"TOKEN APP_ROOT_PATH COMMAND ARGS"がTCPで送信できればよい。
netcatだと例えばecho '1c1cf8a8 /app exec' | nc 127.0.0.1 43537てな感じ。

OSやLinuxディストリによってncコマンドにオプションが必要だったりするので分岐が入っている。
またTOKENはdaemon実行したユーザの$HOME/.cacheあたりに入っているので取り出している。

なおrubyだとこんな感じ。結果の読み出しがちと雑だが...

require 'socket'

Socket.open(:INET, :STREAM) do |sock|
  addr = Socket.sockaddr_in(DAEMON_PORT, DAEMON_HOST)
  sock.connect addr
  sock.write "#{DAEMON_TOKEN} #{APP_ROOT} exec"
  sock.shutdown(Socket::SHUT_WR);
  loop do
    s = sock.gets(chomp: true)
    break unless s
    p s
  end
end

bind問題は一旦後回しとして、docker-composeで起動&外からアクセスする場合、

  • 待ち受けポートの固定
  • ホストのディレクトリを$HOME/.cache/rubocop-daemonにマウント

が必要。つまり

  rubocop_daemon:
    build:
      context: ./backend
    command: bundle exec rubocop-daemon start --no-daemon --port 3001
    volumes:
      - "./backend/tmp/rubocop-daemon:/root/.cache/rubocop-daemon"
      - /app/.bundle
    ports:
      - "3001:3001"
    logging:
      driver: none

という感じ。

ところで、頑張って外からncするのかdocker-compose execでncするのと、どのくらい速度差があるだろうか?

ちなみに他の方法だと compose経由rubocop-daemon exec >> rubyスクリプト(socket) > nc

うむ。docker-compose execの起動はなかなかに遅かった。

daemonの待ち受けアドレスの変更はpullreqするとして、クライアント側のスクリプトはこんな感じになりそう。

rubocop
#!/bin/bash

set -eu
cd $(dirname $0)

NETCAT_COMMAND="nc -N" # 適当に変えるなり分岐するなり

echo $(cat tmp/rubocop-daemon/app/token) /app exec $@ | $NETCAT_COMMAND 127.0.0.1 $(cat tmp/rubocop-daemon/app/port)

exit $(cat tmp/rubocop-daemon/app/status)

※適当に書いて確認してないので注意

オリジナルのrubocop-daemon-wrapperはかなり色々なことをやっていて、適当に並べると

  • daemonのコマンドが存在するか確認
  • ncコマンドのオプション判別
  • ルートディレクトリ名の判別
  • stdinを取り回す機能
  • daemonが起動してなかったら起動する
  • 全てにおいてエラーハンドリング&メッセージ出し

という感じ。利用環境をある程度確定させると殆どの処理は不要になるので、プロジェクトごとに自分で書いたほうがスッキリする。
またdocker-compose環境ではルートディレクトリ名の判別が足枷になってしまう(daemonとwrapperで実行環境が違うため)。

あとは

  • daemonの待ち受けアドレス問題をなんとかする
  • ↑のshellscriptの検証・整理する

したら適当に記事にしたためて終了。

vscodeのformatterとして指定すると対象ファイル名をフルパスで指定されるためにコンテナ内のパスと合わない。

vscode経由だとstdin取り回しは必要だった。

パス問題:

OPTIONS=$(echo "$@" | sed "s|$PWD|\.|g")

stdin -> vscodeは確定で'-s'なので決め打ちでcatしておく

このスクラップは2020/12/26にクローズされました
ログインするとコメントできます