同じにやっても動かない

書いてある通りやっているのに動かないのです

sinatra on docker-compose を Rubymine でデバッグしたい

Railsしかいじったことがないのですが、Stripeのサンプルアプリsinatraで書かれていたのでdocker-composeで動かしてみました。
そこまではわりとすんなり行ったのですが、Rubymineによるデバッグ環境構築で手こずったので備忘録。

環境

  • IntelMac mini
  • OSはMonterey
  • リモート環境のRubyはver3.0.0 (最新じゃないのには理由がある。後述)
  • Rubymineのバージョンは2021.2.4
  • dockerdはRancher Desktop (ver 1.6.1)

Stripeのサンプル動かすのにはまったところ

Webドキュメントには "ruby server.rb" で起動しろと書いてあるのですがこれではだめで、サンプルアプリzipのReadmeにある "ruby server.rb -o 0.0.0.0" が正解です。


もういっこ。
vscodeのテンプレートからDockerfileとdocker-compose作った場合、Gemfile.lockを先に作っておかないとDocker buildでこけます。
今回はローカル環境を使わないので、以下のようにしてリモート環境 (Docker) で作ったGemfile.lockをローカルにコピーします (Gemfileの内容は下記参照)。

$ docker run --rm -v "$PWD":/app -w /app ruby:3.0.0 bundle install

Rubymineでデバッグするための準備

debug-ruby-ide と debase の2つのgemがインストールされている必要があります。
ただ2022.10.25現在、私の環境では3.0.0より新しいrubyだとdebug-ruby-ideのインストール失敗するので、rubyのimageには3.0.0を指定しています。
それと、3.0.0以上のRubyを使う場合、debaseのバージョンは0.2.5.beta2 以上でないとダメだそうです。

DockerfileとGemfileはこんな感じ。

Dockerfile

# ruby:slimだと gem isntallの native extensionのbuildで失敗する
# 3.0.0 より新しいと debug-ruby-ide.gem のインストールで失敗する
FROM ruby:3.0.0

LABEL Name=checkout_test Version=0.0.1

# throw errors if Gemfile has been modified since Gemfile.lock
RUN bundle config --global frozen 1

WORKDIR /app
COPY . /app

# gem install時の develpment tools first 系エラー用
RUN apt-get update
RUN apt-get install -y ruby-dev

COPY Gemfile Gemfile.lock ./
RUN bundle install

CMD ["ruby", "server.rb", "-o", "0.0.0.0"]

Gemfile

source 'https://rubygems.org/'

gem 'sinatra'
gem 'stripe'

# Ruby 3.0 以降はWEBrickが入っていないようなので、アプリケーション・サーバーにpumaをインストール
gem 'puma'

group :development do
  gem 'debase', '>= 0.2.5.beta2'
  gem 'ruby-debug-ide'
end

Rubymineの設定

※ docker-compose up -d で普通に動くところまでできているとします

docker-compose 実行環境の設定

RunやDebug時に、ローカル環境のrubyやgemではなくdocker-composeで起動するDockerコンテナ内のRubyで実行されるようにします

1. ツールバーの Run → Edit Configuration で設定ダイアログを表示させ、docker-composeの新しいconfigurationを開く


2. Docker serverを設定


3. docker-ompose.ymlのありかを設定


Ruby SDK and Gems で新規リモート環境 (dockerコンテナ) のSDKを指定

1. ツールバーのRubyMine → Preference → Language & Frameworks → Ruby SDK and Gemsで "New remote"を選択


2. remote環境の設定


3. プロジェクトルートのマッピング設定


4. リモート環境 (Dockerコンテナ) と Rubymineを同期


Ruby 実行環境の設定

RubymineはRailsと違ってsinatraようのプリセットを持っていないので、RubymineでSinatraをdebugするときはruby scriptとして起動する必要があります。
なのでその実行環境を設定します。

1. ツールバーの Run → Edit Configuration で設定ダイアログを表示させ、Rubyの新しいconfigurationを開く


2. Stripeのサンプルアプリ (sinatra) 起動コマンドを設定


デバッガー起動の前に微調整

上で設定したrubyの実行環境設定でデバッガーを起動すると、Rubymineがport設定を以下のように上書きしてsinatraが起動します。

ports:
    - 1234:1234
    - 26166:26168

最初の1234はRubymineのデバッガーが使うようなので無視。
次の26166 (local):26168 (remote) が罠です。

ホストでは26166をlistenしてリモートの26168に繋ぐということなんですが、
Stripeのサンプルアプリはport 4242をlistenするようになっているのでこのままだとブラウザの要求が届きません。
なので下記のように変えてあげる必要があります。

  • Sinatraはリモート環境 (docker) で動いているので、26168をlisten
  • jsのRedirect (決済完了後に発生) はホスト環境のブラウザで発生するので 26166を指定
  • デバッガー動かさないときも同じように動かせるように、docker-compose.ymlも最初から 26166:26168を入れておくとよい

具体的には以下のようになります。

server.rb

require 'sinatra'
require 'stripe'
# This is your test secret API key.
Stripe.api_key = ''

set :static, true
set :port, 26168 # ← 4242から26168に変更

public/checkout.js

const { error } = await stripe.confirmPayment({
  elements,
  confirmParams: {
    // Make sure to change this to your payment completion page
    return_url: "http://localhost:26166/checkout.html", // ←Redirect先のポート設定を4242から26166に変更 (26168じゃないので注意)
  },
});

docker-compose.yml (port設定)

ports:
    - 26166:26168

これで必要な設定全部終わりです。

デバッガーの起動

起動方法はいろいろありますが、ここではメニューバーの Run → Debug から、先程作ったruby実行環境を選択してデバッグ開始します。

これでブラウザから localhost:26166 (26168じゃないよ) にアクセスすると、こんな感じでちゃんとブレークポイントで止まって変数も読めます。