Selenium Grid on Ubuntu — 分散ブラウザテスト環境のDockerセットアップ

開発環境

この記事のポイント

  • docker run selenium/standalone-chrome の1コマンドで Selenium Grid が起動、Grid が ready になるまで実測 3 秒
  • Docker Compose で selenium/hubselenium/node-chrome を並べると Chrome Node ×2、合計 6 スロットの分散環境が 8.7 秒(実測)で完成する
  • 記事内の数値はすべて Ubuntu 24.04 + Docker 29.6.0 環境で実際に起動して計測したもの
  • 環境汚染ゼロ — ChromeDriver のバージョン管理も不要、コンテナを消せばホストは元通り

Selenium のローカル実行で悩みがちなのは「ChromeDriver と Chrome のバージョンが合わない」問題です。
公式イメージ selenium/standalone-chrome を使えば Chrome・ChromeDriver・Grid サーバーが一式入っており、バージョン管理の手間がなくなります。
私が実際に Ubuntu 24.04 で起動したところ、docker run から /statusready: true を返すまで 3 秒でした。

この記事では Standalone(1コンテナ)と Hub+Node(分散)の 2 構成を実際に動かし、テストコードからセッションを作って確認するところまで手順を載せます。

動作確認済み環境

項目 バージョン / 値 確認方法
OS Ubuntu 24.04.4 LTS lsb_release -a
Docker 29.6.0 docker version
Docker Compose v5.1.4 docker compose version
Selenium Grid 4.44.0 コンテナ起動ログ
Google Chrome(Node) 148.0.7778.178 google-chrome --version(コンテナ内)
ChromeDriver(Node) 148.0.7778.178 chromedriver --version(コンテナ内)
Java(Hub/Node) OpenJDK 21.0.10 java -version(コンテナ内)
Selenium Grid コンポーネント別バージョン(実測)
Selenium Grid コンポーネント別バージョン(実測)

注意

Selenium Grid のイメージは頻繁に更新されます。:latest タグを使うと記事のバージョンと異なる場合があります。本番では selenium/hub:4.44.0 のように固定タグを指定してください。

Standalone モード — 開発・CI 用の最速起動

単一コンテナで Hub・Node・WebDriver エンドポイントをすべて担う構成です。
開発中の動作確認や CI 環境での利用に向いています。

手順1:Docker イメージを pull して起動する




ubuntu@linuxlab: ~
$ docker pull selenium/standalone-chrome:latest
latest: Pulling from selenium/standalone-chrome
Status: Downloaded newer image for selenium/standalone-chrome:latest
$ docker run -d \
–name selenium-grid \
-p 4444:4444 \
–shm-size=2g \
selenium/standalone-chrome:latest
9df8887a3bb3c4a7e9c2f1a83b6d…

--shm-size=2g は重要です。Chrome は /dev/shm(共有メモリ)を描画バッファに使うため、デフォルト 64 MB のままでは複数タブを開いた瞬間にクラッシュします。

手順2:Grid が起動したか確認する




ubuntu@linuxlab: ~
$ curl -s http://localhost:4444/status | python3 -m json.tool | grep -E ‘”ready”|”nodes”‘
“ready”: true,
“nodes”: [

"ready": true が返れば Grid は起動完了です。私の環境では docker run から 3 秒でこの状態になりました。

Docker pull と起動ログ(実測)
Docker pull と起動ログ(実測)

手順3:ブラウザで Grid Console を確認する

http://localhost:4444/ui/index.html にアクセスすると Grid の管理画面が開きます。
登録されたノード数・使用中スロット数・アクティブセッションがリアルタイムで確認できます。

Selenium Grid UI — Standalone モード(実撮影)
Selenium Grid UI — Standalone モード(実撮影)

Standalone モードでは 1 ノード・4 スロットが表示されます(SE_NODE_MAX_SESSIONS を設定しなければデフォルトで CPU コア数に応じて割り当てられます)。

Python からテストを実行する

手順1:selenium パッケージをインストールする




ubuntu@linuxlab: ~
$ pip install selenium
Collecting selenium
Successfully installed selenium-4.x.x

注意

Remote Grid を使う場合、ホスト側の selenium パッケージのバージョンは Grid のバージョンと一致させるのが確実です(pip install selenium==4.44.0)。バージョンが大きく異なると、プロトコル互換性の問題でセッション作成が失敗することがあります。

手順2:テストスクリプトを書く




ubuntu@linuxlab: ~ — test_grid.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument(“–headless”)
options.add_argument(“–no-sandbox”)
options.add_argument(“–disable-dev-shm-usage”)

driver = webdriver.Remote(
command_executor=”http://localhost:4444/wd/hub”,
options=options
)

driver.get(“https://example.com”)
print(driver.title) # => “Example Domain”
driver.quit()

ローカル実行と異なる点は webdriver.Remote(command_executor=...) に Grid の URL を渡すところだけです。
ドライバのバイナリ管理(webdriver-manager 等)は不要で、Grid 側が自動で Chrome を起動します。

アクティブセッション表示(実撮影)
アクティブセッション表示(実撮影)

テスト実行中は Grid Console の Sessions タブにセッションが現れ、どのノードで実行中かが分かります。

Hub+Node 分散構成 — 並列テストを本格的に動かす

Standalone の 4 スロットでは足りなくなったら Hub+Node 構成に移行します。
Hub は WebDriver リクエストのルーターで、実際に Chrome を動かすのは Node です。
Hub と Node を Docker Compose で同一ネットワーク上に起動することで、自動的にセッションが分散されます。

Standalone vs Hub+Node 構成の概念図
Standalone vs Hub+Node 構成の概念図

手順1:docker-compose.yml を作成する




ubuntu@linuxlab: ~/selenium-grid — docker-compose.yml
services:
selenium-hub:
image: selenium/hub:latest
container_name: selenium-hub
ports:
– “4444:4444”
healthcheck:
test: [“CMD”,”curl”,”-f”,”http://localhost:4444/status”]
interval: 5s
timeout: 5s
retries: 10

chrome-node:
image: selenium/node-chrome:latest
shm_size: “2gb”
depends_on:
selenium-hub:
condition: service_healthy
environment:
– SE_EVENT_BUS_HOST=selenium-hub
– SE_EVENT_BUS_PUBLISH_PORT=4442
– SE_EVENT_BUS_SUBSCRIBE_PORT=4443
– SE_NODE_MAX_SESSIONS=3

depends_on: condition: service_healthy の記述が肝で、Hub の /statusready を返すのを確認してから Node が起動します。
これがないと Node が先に起動して Hub に接続できず、登録に失敗することがあります。

手順2:Chrome Node を 2 台で起動する




ubuntu@linuxlab: ~/selenium-grid
$ docker compose up -d –scale chrome-node=2
Container selenium-hub Started
Container selenium-grid-chrome-node-1 Started
Container selenium-grid-chrome-node-2 Started

手順3:ノード登録を確認する




ubuntu@linuxlab: ~/selenium-grid
$ curl -s http://localhost:4444/status | \
python3 -c “import json,sys; v=json.load(sys.stdin)[‘value’]; \
print(‘ready:’, v[‘ready’], ‘/ nodes:’, len(v[‘nodes’]))”
ready: True / nodes: 2

実測では docker compose up -d を叩いてから 2 台の Node が登録完了するまで 8.7 秒でした(compose_up: 6.6 秒 + ノード登録: 2.1 秒)。
合計スロット数は 2 Node × 3 = 6 で、同時 6 本のブラウザセッションが実行できます。

Hub+Node 2台構成の Grid Console(実撮影)
Hub+Node 2台構成の Grid Console(実撮影)
Grid 実測メトリクス(Hub+Node 2台構成)
Grid 実測メトリクス(Hub+Node 2台構成)

手順4:並列テストを実行する




ubuntu@linuxlab: ~ — parallel_test.py
from concurrent.futures import ThreadPoolExecutor
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

GRID_URL = “http://localhost:4444/wd/hub”
URLS = [
“https://example.com”,
“https://httpbin.org/get”,
“https://httpbin.org/status/200”,
]

def run_test(url):
opts = Options()
opts.add_argument(“–headless”)
opts.add_argument(“–no-sandbox”)
driver = webdriver.Remote(GRID_URL, options=opts)
driver.get(url)
title = driver.title
driver.quit()
return f”{url} => {title}”

with ThreadPoolExecutor(max_workers=3) as ex:
results = list(ex.map(run_test, URLS))

for r in results:
print(r)

ThreadPoolExecutor でスレッド数を max_workers=3 にすると、3 セッションが同時に Grid へ投入されます。
Hub が 2 台の Node に均等に振り分けるため、3 テストが同時に実行されます。

Grid Console の見方

Grid UI(/ui/index.html)には 3 つのタブがあります。

タブ 表示内容 使いどころ
Overview 登録ノード数・スロット数・使用率 全体の負荷確認
Sessions 実行中のセッション一覧(ブラウザ種別・Node URI・経過時間) テスト実行中のリアルタイム確認
Node Info 各 Node の IP・ステレオタイプ(ブラウザ種別)・スロット詳細 Node が正しく登録されたか確認
docker-compose.yml 設定例と起動コマンド
docker-compose.yml 設定例と起動コマンド

よくあるエラーと解決策

①「Session not created: Chrome failed to start」

--shm-size=2g を付け忘れた場合に頻発します。Chrome は /dev/shm(共有メモリ)を大量に使うため、デフォルト 64 MB では起動直後にクラッシュします。




ubuntu@linuxlab: ~
# shm-size を明示的に指定する
$ docker run -d -p 4444:4444 –shm-size=2g selenium/standalone-chrome:latest

②Hub+Node で Node が登録されない

SE_EVENT_BUS_HOST に Hub のコンテナ名を正確に設定する必要があります。
また、depends_on: condition: service_healthy で Hub の起動完了を待たせないと、Node が接続先を見つけられず登録失敗します。




ubuntu@linuxlab: ~/selenium-grid
# Hub のログでサービス名(ホスト名)を確認する
$ docker compose logs selenium-hub | grep “Started Selenium Hub”
INFO [Hub.execute] – Started Selenium Hub 4.44.0: http://172.24.0.2:4444
# Node の SE_EVENT_BUS_HOST はサービス名(selenium-hub)に合わせる

③古い selenium パッケージで「InvalidArgumentException」

Grid 4.x は WebDriver W3C プロトコルに完全移行しています。selenium パッケージが 3.x の場合は互換性がなく、セッション作成時にエラーになります。pip install --upgrade selenium で 4.x に上げてください。

著者アイコン
著者アイコン

Hub+Node で一番詰まったのは depends_on の書き方でした。condition: service_healthy を付けるだけで Node の起動タイミングが Hub healthcheck 後に固定され、今回の実測でも compose up から 8.7 秒で 2 Node が揃いました。ここだけは覚えておいて損はないです。

まとめ

この記事のまとめ

  • Standalone モード: docker run -p 4444:4444 --shm-size=2g selenium/standalone-chrome:latest の 1 コマンドで起動、3 秒で ready
  • Hub+Node モード: Docker Compose で Hub×1+Node×2 を定義、condition: service_healthy でノード登録を安定化。8.7 秒(実測)で 6 スロット
  • テストコードは webdriver.Remote(command_executor="http://localhost:4444/wd/hub", ...) に変えるだけ
  • --shm-size=2g なし・Hub のホスト名ミス・selenium 3.x のまま は三大トラブル
  • Chrome バージョン管理は不要 — コンテナが Chrome と ChromeDriver を同バージョン(148.0.7778.178)で一括管理

分散テスト環境を一通り手元で試せたら、次は VPS 上で動かすことも視野に入ってきます。
並列セッションを常時動かすなら 2GB RAM 以上のプランが現実的です。

VPS の選び方が気になる方は もあわせて読んでみてください。

コメント

タイトルとURLをコピーしました