ChromeDriverのバージョン自動判別

Dockerコンテナビルド後にRSpecでエラー

Dockerコンテナを久々にビルドしてRSpecを実行したらエラーが発生しました。

1
2
Selenium::WebDriver::Error::SessionNotCreatedError:
session not created: This version of ChromeDriver only supports Chrome version 84

原因はChromeとChromeDriverのバージョンがあっていないからです。

以前は動作していましたが、今回コンテナを再ビルドしたことによって問題が発生したような形になっています。原因は何でしょうか。

DockerでChromeDriverのバージョンを固定で指定することの問題点

Dockerfileを見てみましょう。

1
2
3
4
5
6
7
8
RUN yum install -y unzip \
https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm && \
sed -i 's|HERE/chrome"|HERE/chrome" --disable-dev-shm-usage --disable-setuid-sandbox --no-sandbox|g' \
"/opt/google/chrome/google-chrome" && \
cd /usr/local/src/ && \
wget https://chromedriver.storage.googleapis.com/84.0.4147.30/chromedriver_linux64.zip && \
unzip chromedriver_linux64.zip && \
install chromedriver /usr/local/bin/

この記述を見ると、google-chrome-stable_current_x86_64.rpmがバージョン84であるときは正常に動作するのですが、バージョンが更新されてしまうと、バージョン固定でインストールしているChromeDriverとバージョンが合わなくなってしまいます。

ということはDockerコンテナをビルドするタイミングでうまくいったり行かなかったりしてしまうということです。これはよくないですね。

ChromeDriverのバージョン自動判別

そこでインストールされるGoogle ChromeのバージョンにあったChromeDriverをインストールするように変更してみます。

先ほどのDockerfileのRUNコマンドを以下のように変更してみます。

1
2
3
4
5
6
7
8
9
10
RUN yum install -y unzip \
https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm && \
sed -i 's|HERE/chrome"|HERE/chrome" --disable-dev-shm-usage --disable-setuid-sandbox --no-sandbox|g' \
"/opt/google/chrome/google-chrome" && \
cd /usr/local/src/ && \
wget -O LATEST_RELEASE_ "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$(rpm -q --queryformat='%{Version}' google-chrome-stable | sed -e 's/[.][0-9]*$//')" && \
wget "https://chromedriver.storage.googleapis.com/$(cat LATEST_RELEASE_)/chromedriver_linux64.zip" && \
rm LATEST_RELEASE_ && \
unzip chromedriver_linux64.zip && \
install chromedriver /usr/local/bin/

変更があったのは以下の3行です

1
2
3
wget -O LATEST_RELEASE_ "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$(rpm -q --queryformat='%{Version}' google-chrome-stable | sed -e 's/[.][0-9]*$//')" && \
wget "https://chromedriver.storage.googleapis.com/$(cat LATEST_RELEASE_)/chromedriver_linux64.zip" && \
rm LATEST_RELEASE_ && \

なにを行なっているのか一つずつみていきましょう。

インストールされているChromeのバージョン取得

まずは1行目のコマンド置換している箇所を見ていきます。

1
rpm -q --queryformat='%{Version}' google-chrome-stable

インストールされているgoogle-chromeをrpmコマンドを使って問い合わせています。--queryformatというオプションはあまり見かけませんが、manページによると以下のようなオプションです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
検索オプション
rpm 検索の一般的な形式は:

rpm {-q|--query} [select-options] [query-options]

表示されるパッケージ情報の書式を指定することができる。 そうするために
は、

--qf|--queryformat QUERYFMT

オプションを使う。 QUERYFMT が書式文字列である。検索の書式は、標準的な
printf(3) の書式の修正である。書式は静的な文字列 (改行・タブ・その他の
特殊文字の、C 言語の標準的な文字エスケープを含む)と、 printf(3) 型の書
式文字列からなる。 しかし rpm は表示する型を既に知っているので、型指定
は省略されるべきである。 代わりに {} で囲まれた、表示されるへッダーのタ
グ名が使用される。 タグ名に大文字/小文字の区別はなく、タグ名の先頭の
RPMTAG_ 部分も省略することができる。

利用できるタグはrpm --querytagsを実行することで全て表示することができます。AmazonLinux2で実行したら、205ありました。

それではrpmコマンドを実際に実行してみます。

1
2
# rpm -q --queryformat='%{Version}' google-chrome-stable
86.0.4240.75

バージョン番号のみ表示されました。

ちなみに通常の出力は以下です。

1
2
# rpm -q google-chrome-stable
google-chrome-stable-86.0.4240.75-1.x86_64

Chromeのバージョン番号の整形

バージョン番号をパイプで渡してsedに入力として渡しています。sedの正規表現を見てみましょう。

1
's/[.][0-9]*$//'

[.]\.でも良さそうですね。数字が0個以上繰り返して、$は行末にマッチします。バージョン番号の最後のオクテットを''に置換しているということになります。

実際に試してみましょう。

1
2
$ echo '86.0.4240.75' | sed -e 's/[.][0-9]*$//'
86.0.4240

これでコマンド置換している箇所の文字列が取得できました。次は実際にwgetをしてみます。

ChromeDriverのバージョンを保存

先ほどあったコマンド

1
wget -O LATEST_RELEASE_ "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$(rpm -q --queryformat='%{Version}' google-chrome-stable | sed -e 's/[.][0-9]*$//')"

1
wget -O LATEST_RELEASE_ "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_86.0.4240"

であることがわかりました。wgetの-Oオプションは、取得したコンテンツを出力するファイル名を指定します。

実際に実行してしましょう。

1
2
3
4
5
6
7
8
9
$ wget -O LATEST_RELEASE_ "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_86.0.4240"
--2021-02-22 21:01:33-- https://chromedriver.storage.googleapis.com/LATEST_RELEASE_86.0.4240
接続要求を送信しました、応答を待っています... 200 OK
長さ: 12 [text/plain]
`LATEST_RELEASE_' に保存中

LATEST_RELEASE_ 100%[=========================================================================================================================>] 12 --.-KB/s 時間 0s

2021-02-22 21:01:33 (186 KB/s) - `LATEST_RELEASE_' へ保存完了 [12/12]

LATEST_RELEASE_に保存できました。中身を確認します。

1
2
$ cat LATEST_RELEASE_ 
86.0.4240.22

これでインストールすべきChromeDriverのバージョンが

ChromeDriverのダウンロード

実際にChromeDriverがダウンロードできるかどうか確認します。

1
2
3
4
5
6
7
8
9
$ wget "https://chromedriver.storage.googleapis.com/$(cat LATEST_RELEASE_)/chromedriver_linux64.zip"
--2021-02-22 21:14:24-- https://chromedriver.storage.googleapis.com/86.0.4240.22/chromedriver_linux64.zip
接続要求を送信しました、応答を待っています... 200 OK
長さ: 5456932 (5.2M) [application/zip]
`chromedriver_linux64.zip' に保存中

chromedriver_linux64.zip 100%[=========================================================================================================================>] 5.20M 3.17MB/s 時間 1.6s

2021-02-22 21:14:26 (3.17 MB/s) - `chromedriver_linux64.zip' へ保存完了 [5456932/5456932]

無事ダウロードできました。これで、いつでもChromeのバージョンにあったChromeDriverがダウンロード、インストールできるようになりました。

まとめ

  • ChromeDriverの最新バージョンはChromeのバージョンの一部で構成されるURLで取得できる
  • そのURLはhttps://chromedriver.storage.googleapis.com/LATEST_RELEASE_バージョン番号である
  • Chromeのバージョンは少し加工する必要がある