経緯
お仕事で、CI 環境用に Selenium Grid を Docker で稼動させています。 以前は Hub は別サーバに立てて、Node を Docker コンテナとして複数起動できるように構築していましたが、 いろいろあって Hub も Docker コンテナとしてしまおう、と考えました。
簡単にこんな感じです。
いざ Hub の Docker コンテナを作ろうとした際
「とりあえず java が動けばいいんだから Node のイメージそのまま流用できるよな」 「いやいやここはやはり Hub/Node はしっかり分けた方がいいだろう」 「じゃあ Hub 用と Node 用で Dockerfile 作ってこ?」 「でも Hub も Node も Java 使うんだから、まずは SeleniumBase という とりあえず Java と selenium.jar 入ってるイメージ作って、そいつを FROM していく?」 「つまり Dockerfile は3つか。さてディレクトリ構成どうしよう」
みたいなことを考えるわけです。 よしならば始めようと思った時にチームリーダーから
似たようなやつ Docker Hub に既にあるんじゃね?
ははまさか、って思ったらやっぱりありました。
https://registry.hub.docker.com/repos/selenium/
しかもだいたい揃ってる。こいつを使っていこう。
今回の環境
OSX Yosemite で boot2docker 使いました。
$ boot2docker version Boot2Docker-cli version: v1.3.2 Git commit: e41a9ae $ docker version Client version: 1.3.2 Client API version: 1.15 Go version (client): go1.3.3 Git commit (client): 39fa2fa OS/Arch (client): darwin/amd64 Server version: 1.3.2 Server API version: 1.15 Go version (server): go1.3.3 Git commit (server): 39fa2fa
boot2docker
および fig
は Homebrew でインストールしてあります。
使ってみる
今回使うのはこの2つ
README や Dockerfile、使用されているスクリプトを読むと --link
オプションで Node → Hub の接続情報を補充している模様。
- https://github.com/SeleniumHQ/docker-selenium/tree/master/Hub#how-to-use-this-image
- NodeBase/entry_point.sh
コンテナ起動に docker run
を手で打つのはつらいので、fig を利用してみました。
fig.yml
hub: image: selenium/hub ports: - "4444" // (1) node: image: selenium/node-firefox expose: - "5555" // (2) links: - hub
無くても問題ないのですが、Selenium Grid 画面を見たかったので Port Forwarding
Docker ホスト外から利用する時はポート固定されてると楽なので、
"4444:4444"
とかselenium/node-base
に EXPOSE 指定が無かったため、node.expose
を追加してあります。Node にアクセスするのは同じ Docker ホスト上の Hub だけ想定しているので
ports
指定は不要
起動
$ pwd /tmp $ fig up -d hub Creating tmp_hub_1.. $ fig scale node=5 Starting tmp_node_1... Starting tmp_node_2... Starting tmp_node_3... Starting tmp_node_4... Starting tmp_node_5...
docker ps
はこんな感じ
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7077acdb0e47 selenium/node-firefox:latest "/opt/bin/entry_poin 7 seconds ago Up 5 seconds 5555/tcp tmp_node_5 254af6c66a11 selenium/node-firefox:latest "/opt/bin/entry_poin 7 seconds ago Up 5 seconds 5555/tcp tmp_node_4 37cf71984ad4 selenium/node-firefox:latest "/opt/bin/entry_poin 7 seconds ago Up 6 seconds 5555/tcp tmp_node_3 7bf7fe5bc71e selenium/node-firefox:latest "/opt/bin/entry_poin 7 seconds ago Up 6 seconds 5555/tcp tmp_node_2 b2f3383f15dc selenium/node-firefox:latest "/opt/bin/entry_poin 7 seconds ago Up 6 seconds 5555/tcp tmp_node_1 2e0b30a2b22e selenium/hub:latest "java -jar /opt/sele 14 seconds ago Up 13 seconds 0.0.0.0:49156->4444/tcp tmp_hub_1
起動してるっぽい
Grid の様子をチェック
Selenium Grid のコンソールは http://{hub の IPaddr}:{hub の port}/grid/console
にアクセスすると見れます。
ここでいう hub の IPaddr および hub の port は
IPaddr
$ boot2docker ip The VM's Host only interface IP address is: 192.168.59.103
port
$ docker port tmp_hub_1 4444/tcp -> 0.0.0.0:49156
なので http://192.168.59.103:49156/grid/console
となります。
アクセスするとお馴染の画面が表示されます。
ちゃんと scale node=5
した数だけ、Node が Hub に登録されています。
※ Hub に認識されるまで時間かかる時もあります。Hub の cycle なんちょかを短かくすればい早くなるんだろうか。
Grid を使ったデモアプリ
アプリってほどでも無いですが、とりあえず一気に5つの Selenium WebDriver を走らせてみる系
# Gemfile source 'https://rubygems.org' gem 'selenium-webdriver' gem 'parallel' # main.rb require 'selenium-webdriver' require 'parallel' urls = [ 'https://github.com', 'https://hub.docker.com', 'https://bitbucket.org', 'https://www.heroku.com', 'http://azure.microsoft.com/ja-jp/' ] Parallel.each_with_index(urls, in_threads: 5) do |url, index| driver = Selenium::WebDriver.for :remote, url: 'http://192.168.59.103:49156/wd/hub' driver.navigate.to url driver.save_screenshot "screenshot#{index}.png" end
こいつを
$ bundle install --path vendor/bundle $ bundle exec ruby main.rb $ ls Gemfile main.rb screenshot1.png screenshot3.png vendor Gemfile.lock screenshot0.png screenshot2.png screenshot4.png
とすると、とりあえず画像が取得できる。まあこの例だと並列じゃなくてもできるんだけど。
ちなみに実行中のコンソールも無事5つ同時に使われている
イメージの中身見てみる
1. Base
github.com/SeleniumHQ/docker-selenium/Base/Dockerfile
JRE インストールして selenium jar とってきて seluser 作る。シンプル
2. Hub
github.com/SeleniumHQ/docker-selenium/Hub/Dockerfile
4444 ポートで待ち受ける Hub モード起動。
3. NodeBase
github.com/SeleniumHQ/docker-selenium/NodeBase/Dockerfile
ブラウザを動かす仮想フレームバッファとしては Xvfb を使用している。 タイムゾーンや Xvfb のパラメータをセット。
github.com/SeleniumHQ/docker-selenium/NodeBase/entry_point.sh
/opt/selenium/config.json
および --link
で Hub と関連付けされている前提で処理が組まれている。
後述する NodeFirefox
や NodeChrome
ではこれらが設定されている。
4. NodeFirefox
github.com/SeleniumHQ/docker-selenium/NodeFirefox/Dockerfile
Firefox をインストールし、それ用の Selenium Profile をセット。
まとめ
Selenium Profile やタイムゾーンだったりを変更したい場合は、 FROM selenium/node-firefox
した Dockerfile で再度記述して上書きもできるし特に問題無く使えた。
Selenium 公式が出しているイメージだしどんどん使っていこう。
参考
- https://registry.hub.docker.com/repos/selenium/
- https://github.com/SeleniumHQ/docker-selenium
- https://groups.google.com/d/topic/selenium-developers/d1C5GL53ua0/discussion
- Docker Hub に登録したぜーっていうポスト。Xvfb じゃなくて別のどうだい?とかいろいろまだまだ変わるかもーとのこと