docker環境のrails5をstep実行でdebugする
概要
先日 dockerでrails5環境構築で開発環境を作りました。
で、やはり開発する上ではguiでstep実行できると楽だなと思い、
Visual Studio Codeを使ってRailsをデバッグ実行してみよう
の記事を見つけたのでdocker-machine上で実行されているrailsに対して試してみようとしたところ、先日に引き続きハマり倒したのでその作業メモです。
目標のデバッグ環境
構築した dockerでrails5環境構築の環境は下記のような構成で動いています。
この環境でホストOS(osx)で実行しているVisual Studio Codeのデバッガでステップ実行したいわけです。
以下先日の「dockerでrails5環境構築」の状態からの変更点を記載していきます。
railsコンテナの設定
基本的には「Visual Studio Codeを使ってRailsをデバッグ実行してみよう」の通りに進めていきます。
-
Gemの追加
ruby-debug-ide
とdebase
をdevelopment
環境に追加します。app/Gemfilegroup :development do # 〜略〜 gem 'ruby-debug-ide' gem 'debase' end
-
rdebug-ideでrailsを起動するために起動スクリプト修正
コンテナ起動時に環境変数
DEBUG_MODE
を渡すことでデバッグモードでrailsが起動できるように変更します。app/bin/run-docker-compose.sh#!/bin/sh SCRIPT_DIR=$(cd $(dirname $0) && pwd) export DB_DOCKERFILE_DIR=${SCRIPT_DIR}/../db export WEB_DOCKERFILE_DIR=${SCRIPT_DIR}/../web export WEB_APP_ROOT_DIR=${SCRIPT_DIR}/../../app export MYSQL_DATABASE=mydb export MYSQL_USER=dbuser export MYSQL_PASSWORD=dbuser_pass export MYSQL_ROOT_PASSWORD=root export START_RAILS_COMMAND="bundle install --path=vendor/bundle && rm tmp/pids/server.pid;" # debugモードに切り替える設定 if [ "$DEBUG_MODE" = "1" ] ; then # debug mode START_RAILS_COMMAND="${START_RAILS_COMMAND} bundle exec rdebug-ide --host 0.0.0.0 --port 1234 --dispatcher-port 26162 -- bin/rails s -b 0.0.0.0" else # normal mode START_RAILS_COMMAND="${START_RAILS_COMMAND} bin/rails s -b 0.0.0.0" fi YML_FILE=$SCRIPT_DIR/docker-compose.yml docker-compose -f $YML_FILE $*
起動コマンド
command
を直書きしていた部分を↑で設定したSTART_RAILS_COMMAND
で置き換えます。
またrdebug-ide
が使うポートをports
に追加します。app/bin/docker-compose.ymldb: container_name: db build: ${DB_DOCKERFILE_DIR} ports: - "3306:3306" environment: MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} web: container_name: web build: ${WEB_DOCKERFILE_DIR} ports: - "3000:3000" - "1234:1234" - "26162:26162" links: - db:db volumes: - ${WEB_APP_ROOT_DIR}:/var/myapp environment: DATABASE_NAME: ${MYSQL_DATABASE} DATABASE_USER: ${MYSQL_USER} DATABASE_PASS: ${MYSQL_PASSWORD} DATABASE_HOST: db command: sh -c "${START_RAILS_COMMAND}"
- railsコンテナの
Dockerfile
のEXPOSE
にも1234
,26162
を追加します。
〜略〜 EXPOSE 3000 1234 26162 〜略〜
これでデバッグモードで起動出来るようになったので、
build
しなおしてから起動確認します。
下記のようにFast Debugger
の表示になってwait状態になれば起動成功です。
(この状態ではまだrails
は起動されていないのでブラウザでアクセスしても何も表示されません。)# Dockerfileを直したので再ビルド docker/bin/run-docker-compose.sh build # DEBUG_MODEを指定して起動スクリプトを実行 DEBUG_MODE=1 docker/bin/run-docker-compose.sh up 〜略〜 web | Fast Debugger (ruby-debug-ide 0.6.0, debase 0.2.1, file filtering is supported) listens on 0.0.0.0:1234
- railsコンテナの
Visual Studio Codeの設定
Ruby
用の拡張機能のインストールについては
を参考にしてください。
この記事にならってデバッグ用の設定ファイルを作成します。
ただし今回はrails
はdocker
で動いているのでremoteHost
の設定をdocker-machine
のipに変更し、remoteWorkspaceRoot
をコンテナ内でデプロイしているパス(ここでは/var/myapp
)に変更しておきます。
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for rdebug-ide",
"type": "Ruby",
"request": "attach",
"cwd": "${workspaceRoot}",
"remoteHost": "192.168.99.100",
"remotePort": "1234",
"remoteWorkspaceRoot": "/var/myapp",
"useBundler": true
}
]
}
これでVisual Studio Code
側の設定も終わったので、先日作ったhello_controller.rb
にブレイクポイントを設定してみます。
デバッグ実行
これでrails
側もVisual Studio Code
側も設定ができたのでデバッグ実行!ということで試してみました。
・・・が、案の定、全くうまく行かず。いくつもハマりどころが合ったので項目毎に解決方法を記載していきます。
-
デバッグサーバが立ち上がらない問題
先ほどの設定確認ではすんなり
rdebug
サーバが立ち上がっていましたが、まずここでつまずきました。
元々遅いと思っていたのですが、このデバッグサーバに関しては耐え切れないほど起動が遅くてとても使ってられませんでした。原因はホスト側でソースを編集できるように
VOLUME
でapp
フォルダ以下をマウントしていたのが原因のようでした。
Virtual Box
の共有フォルダはすこぶる遅いらしく普通の方法ではどうしようもないようです。そこでいろいろ調べたところ、
の記事を見つけました。
Virtul Box
の共有フォルダをnfs
でマウント出来るようにしてくれるツールだそうです。
開発元のサイトを見てみるとHomebrew
でインストールもできて、引数無しで実行した場合はdocker-machine
で通常行われる/User
以下を(macの場合)設定してくれるそうなので、簡単に導入できました。brew install docker-machine-nfs
でインストールし、
docker-machine
が起動されている状態で、そのdocker-machine
名(ここではdefault
)を引数に実行するだけのようです。docker-machine-nfs default 〜略〜 │~ |+ 16 # debugモー» -------------------------------------------- │~ |+ 17 if [ "$DEBU» │~ |+ 18 # debug m» The docker-machine 'default' │~ |+ 19 START_RAI» is now mounted with NFS! │~ |+ 20 else↲ │~ |+ 21 # normal » ENJOY high speed mounts :D │~ |+ 22 START_RAI» │~ |+ 23 fi↲ --------------------------------------------
途中
sudo
を使っているようでパスワードを求められたのでパスワード入力し、上記のような表示になればOKです。
なんとも頼もしいメッセージです。
で、結果はというと、とんでもなくデバッグサーバの起動が早くなりました。というかすべてが早くなりました。感謝。 -
途中でステップ実行がふんずまる問題
これでデバッグサーバがまともに動くようになったのでデバッグしてみます。
# debugサーバ実行 DEBUG_MODE=1 docker/bin/run-docker-compose.sh up 〜略〜 web | Fast Debugger (ruby-debug-ide 0.6.0, debase 0.2.1, file filtering is supported) listens on 0.0.0.0:1234
デバッグ準備OKなので、Visual Studio Code
側からアタッチします。
先ほど作ったデバッグ設定を選択して起動します。
すると、railsのコンソール側でpumaが起動します。
web | => Booting Puma
web | => Rails 5.0.0.beta3 application starting in development on http://0.0.0.0:3000
web | => Run `rails server -h` for more startup options
web | => Ctrl-C to shutdown server
web | Puma starting in single mode...
web | * Version 3.4.0 (ruby 2.3.0-p0), codename: Owl Bowl Brawl
web | * Min threads: 5, max threads: 5
web | * Environment: development
web | * Listening on tcp://0.0.0.0:3000
web | Use Ctrl-C to stop
この状態で、http://192.168.99.100:3000/hello
にアクセスします。
するとバッチリhello_controller.rb
に仕掛けたブレイクポイントで止まります・・・・・止まりますが、そのままステップ実行していくと、どうしても途中でステップ実行が止まります。しかもページもずっとロード中のままぐるぐる回り続けます。。
全く止まらないとかエラーになるとかならまだ分かるんですが、途中までステップ実行出来るだけにこれにはハマりまくりました。
で、いろいろ考えたところ、だいたいローカルホストでうまくいくのに、docker-machine
でうまくいかない時の定番はネットワーク問題なので、それならlocalhost
と通信している体にしてやろう!ということで、ポートフォワーディングで、ローカルの1234
, 26162
とdocker-machine
の同ポートを繋いでやることにしました。(コンテナとdocker-machine
の同ポートは本来のdocker
の機能でフォワードされています。)
要は下記のような感じです。(以下のVSC
はVisual Studio Code
のこと)
もともと
VSC
----> docker-machineのポート1234
----> railsコンテナのポート1234
という経路でデバッグサーバにアクセスしていたところを
VSC
----> localhostのポート1234
----> docker-machineのポート1234
----> railsコンテナのポート1234
と、ローカルの1234
ポート経由でアクセスしようということです。
ということで、VisualStudioCode
のデバッグ設定を変更します。
下記のようにremoteHost
をlocalhost
にします。
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for rdebug-ide",
"type": "Ruby",
"request": "attach",
"cwd": "${workspaceRoot}",
"remoteHost": "localhost",
"remotePort": "1234",
"remoteWorkspaceRoot": "/var/myapp",
"useBundler": true
}
]
}
次に、ローカルのポートをdocker-machine
のポートに繋ぎます。
docker-machine
のssh
コマンドにはその後の引数にssh
コマンドのポートフォーワードの書式をそのまま書けるのでそれを利用します。
フォワードするだけなので、適当にターミナルを起動して下記コマンドでdocker-machine
にログインしたらそのままほったらかします。
docker-machine ssh default -L 1234:localhost:1234 -L 26162:localhost:26162
この状態で、再度デバッグサーバを立ち上げて、デバッグしてみるとバッチリステップ実行できました。
- デバッグコンソールで変数を参照すると時々止まる問題
これは未だ原因不明なのですが、ステップ実行中にVisual Studio Code
のデバッグコンソールで変数をinspectするとコンソールに内容が表示できて便利なのですが、これを行うとタイミングによって(?)デバッグセッションが止まってしまいます。。とりあえず左側のペインで変数の内容とコールスタックが確認できるので致命的に困るようなことでもないため放置です。どなたか解決方法ご存知でしたら教えて下さい。
-
絶対間違ってない箇所で謎の引数違うよエラーが出る問題
これは今回の記事用に作ったリポジトリで起きなかったので微妙なのですが、
byebug
gemと一緒にruby-debug-ide
gemを使うと変なエラーが出ることがあるそうです。実際別のプロジェクトで試していた時にpry-byebug
を同時に使っていたのですが、ブレイクポイントの箇所のコードで明らかに問題ない処理がエラーになって落ちてしまっていました。
や
http://stackoverflow.com/questions/31046586/cant-debug-rails-app-in-rubymine
を参照しました。
ここまでの内容を反映したのを
https://github.com/pocari/rails5-docker-sample/tree/ver02-enable-remote-debug
にあげています。