🍣

Capybaraのためのcompose.ymlの設定

に公開

こんにちは

プログラミングスクールで Ruby on Rails を主に学習している、りゅうという者です。

卒業制作でWebアプリを作成しています。
その中で今回 Capybara を使うときに、compose.yml の設定をしていない関係でエラーが起きたので、記事にさせていただきました。

⚠️ 注意

プログラミング初心者のため、間違いがあるかもしれません。
また、お使いのPCや環境によってはうまく動作しない可能性もございます。

お気付きの点がありましたら遠慮なく教えていただけると嬉しいです。
よろしくお願いいたします。

言葉の理解には ChatGPT を多く使っているので、正確性には欠けるかもしれません。
より正確性を求めるには 公式を参考 にしてください。

💡 前提

  • Capybaraに必要なgemをインストールしている。
  • Capybaraに関する設定やテストの実装は終わっている。

🧭 Capybaraの流れ

Capybara(Railsのテスト)が「このページを開いて」「このボタンを押して」などの命令を出します。 その命令を Selenium Server に送って、
Selenium Server がその命令を WebDriver に伝えて実際にブラウザ(Chrome)を操作する流れになります。

┌────────────────────────────┐
│         Docker環境(共通ネットワーク)          │
│────────────────────────────│
│                                                                │
│  🧱 webコンテナ (Rails + Capybara)                           │
│      ↓                                                       │
│      ↓ HTTPリクエスト                                         │
│      ↓ (SELENIUM_DRIVER_URL=http://chrome:4444/wd/hub)      │
│                                                                │
│  🌐 chromeコンテナ (Selenium Server + Chromeブラウザ)         │
│      ↑                                                       │
│      └── SeleniumがWebDriverに命令を伝え、Chromeを操作       │
│                                                                │
└────────────────────────────┘

🧪 Capybaraのテスト実行時に出たエラー

Capybaraの設定やテストの実装が終わって、
以下のコマンドを実行しました👇

docker compose exec web bundle exec rspec spec/system/users_spec.rb

# ./spec/system/users_spec.rb:6:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Errno::ECONNREFUSED:
#   Connection refused - connect(2) for "127.0.0.1" port 4444
#   /usr/local/bundle/gems/timeout-0.4.3/lib/timeout.rb:185:in `block in timeout'

🧐 エラーと原因

Rails(Capybara / Seleniumクライアント)が
127.0.0.1:4444」に接続しようとして失敗しました。
127.0.0.1webコンテナのOS自身を指します。

つまり、Railsがwebコンテナに接続しようとしています。
本来はRailsがchromeに接続しないといけません。

🔧 対応

なので、以下を追加しました(dbなど無関係な部分は省略しています)

compose.yml
version: '3'
services:
  web:
    build:
      context: .
    command: bash -c "bundle install && bundle exec rails db:prepare && rm -f tmp/pids/server.pid && ./bin/dev"
    tty: true
    stdin_open: true
    volumes:
      - .:/myapp
      - bundle_data:/usr/local/bundle:cached
      - node_modules:/myapp/node_modules
    environment:
      TZ: Asia/Tokyo
+     SELENIUM_DRIVER_URL: http://chrome:4444/wd/hub
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
+     chrome:
+       condition: service_started
+  chrome:
+    image: seleniarm/standalone-chromium:latest
+    ports:
+      - 4444:4444

📘compose.ymlとは

複数のコンテナをまとめて構成・起動するための設定ファイル。
ここで言うコンテナとは、db、webやchromeを指します。

🧩加筆したコードの理解

compose.yml
+  chrome:
+    image: seleniarm/standalone-chromium:latest
+    ports:
+      - 4444:4444

chromeと言うコンテナを作成しようとしています。imageは設計図のイメージで、ここではchromeとseleniumの設計図です。
ポート番号は4444を指定します。

compose.yml
    depends_on:
      db:
        condition: service_healthy
+     chrome:
+       condition: service_started

depends_onはコンテナの起動順序の制御です。
web:に書いているので、
dbコンテナが立ち上がったらwebコンテナを立ち上げてと明示しています。

chromeも同じです。

conditionなどは以下の記事が参考になります。↓↓
https://qiita.com/waniwaninowani/items/d43c4b8cea690a50581f

compose.yml
    environment:
      TZ: Asia/Tokyo
+     SELENIUM_DRIVER_URL: http://chrome:4444/wd/hub

environment(環境変数)とはコンテナ起動時に読む設定項目です
ここで設定した値は、Railsアプリの中から ENV["変数名"] で使えます。

spec/support/capybara.rb
Capybara.register_driver :remote_chrome do |app|
  options = Selenium::WebDriver::Chrome::Options.new
  省略
  ENV['SELENIUM_DRIVER_URL'], capabilities: options)
end

と書いています。この中のENV['SELENIUM_DRIVER_URL']に先ほどのURLの値が入ります。

URLはSeleniumの住所のイメージです。
具体的にはChromeコンテナを作ってポート番号を指定した場所になります。
wd/hubはSelenium Server が自動で提供しているAPIのルートパスです。

まとめ

Capybara(Railsのテスト)がwebコンテナを探していた原因でエラーが起きました。
compose.ymlにChromeに関する設定を加筆したことで解決できました。
Dockerにブラウザ(Chromeコンテナ)を追加して、その中で自己完結していくんですね。

間違いがあったらぜひ教えてください!

参考になった記事

https://qiita.com/gon0821/items/2ab56df440e057f9d1b7

https://qiita.com/gon0821/items/77369def082745d19c38

https://zenn.dev/masanao/articles/d24a07385e4d0c

https://qiita.com/zuuumiii/items/0ebab990b1fc707ae309

最後に

Dockerのイメージは抽象的で難しいですが、理解が少し深まったと思います。
noteで卒業制作の過程を書いています。
よかったらぜひおねがします!
https://note.com/ryu0121_it/n/n154649d7dce1

Discussion