rails dbconsoleでパイプラインを使えなくなって困った

Ruby on Railsにはrails dbconsoleというコマンドがある。config/database.ymlの接続情報を使ってデータベースクライアント(mysqlとか、psqlとか)を立ち上げてくれる、やや便利なやつで、DBからちょっとした情報を手軽に得たいときに重宝している。たとえば、こんな感じの使い方である。

$ echo "show variables" | bin/rails dbconsole -p

ところが、これが私の環境に限りいつのまにか使えなくなっていたので、さて困ったぞと。
実行してみると、何の出力も無く、ただ終了する。どうやら"show variables"が最終的に呼び出されることになるmysqlコマンドまで渡っていないようなのである。

さて、何が起きているのか。パイプラインなんてかなり基本的な処理なので、むしろどうやった壊せるのか。見当も付かない。

原因

ちょっと…いや、だいぶ…調べて、原因を突き止めた。database.ymlの書き方が悪い。

development:
  host: <%= `docker-machine ip default`.chomp %>

おわかりいただけただろうか。

現在、開発で用いるDBはすべてdocker-machineを使ってコンテナとして動かしている。docker-machineはDockerを動かすために必要なLinux OSを仮想マシンとして起動するが、このマシンのIPアドレスは再起動のタイミングで変化する可能性がある。そこで、docker-machine ip {マシン名}というコマンドでIPアドレスを都度調べるようにすると、不意の変化があっても焦らずに済む。

そういうわけで、いつでも正しいIPアドレスを取れるようこのような書き方をしたのであったが、まさにこれのせいでrails dbconsoleが思い通りに動かなくなった。というのも、パイプラインからの入力がmysqlコマンドに到達する前に`docker-machine ip default`が奪ってしまうからである。

対策

仕方が無いので、``の使用を避けるようにした。

development:
  host: <%= ENV['DOCKER_HOST'].scan(/\d+\.\d+\.\d+\.\d+/).first %>

docker-machineを使っているということは、その環境ではeval "$(docker-machine env default)"しているということであり、export DOCKER_HOST=tcp://192.168.99.100:2376的な設定がなされているということである。これを利用しない手は無い。

試してみると、元通りに動く。もともと、設定ファイルを一個読み込むためにプロセスを余計に1つ立ち上げるほうがやりすぎだったのである。一件落着。

同じようにdocker-machineを使っている人はそこそこにいると思うのだが、みなどうしているのだろう?IPアドレスが変わるといってもまれだから決めうちか。

おまけ

今度はPow上で動かなくなった。bin/rails serverした場合とは違って、DOCKER_HOSTなどという環境変数が無いからである。そりゃそうだ。

アプリケーションのルートディレクトリに .powrc を足して解決。

eval "$(docker-machine env default)"