🐳

Docker環境で任意のバージョンのChromeとChromeDriverを導入

2024/08/02に公開

概要

SeleniumでChromeを操作するためには、ChromeとChromeDriverのバージョン互換性が重要です。この記事では、Dockerを使用して、任意のバージョンのChromeとChromeDriverを導入する方法を紹介します。

Selenium 4.11以降の場合は、Selenium Managerが最も簡単な方法です。

一方で、DockerイメージにChromeやChromeDriverを含めておきたい場合や、古いバージョンのSeleniumを使用したい場合には、Chrome for Testingを直接インストールする方法があります。

ただし、Docker環境では、いずれの場合もブラウザの依存関係を別途導入する必要があるようです。

ちなみに上記はChrome 115以降を使用するケースを想定しています。Chrome 114以前を使用したい場合は、未検証ですが下記のようになるかと思います。

バージョン Chrome ChromeDriver
113〜114 Chrome for Testingを入手 webdriver-managerなどのライブラリを使用して入手するか、以前のダウンロードページからインストール
〜112 公式提供なし 同上

Selenium Manager

Selenium 4.11以降では、ベータ版のSelenium Managerを使用して指定したバージョンのChromeとChromeDriverのバージョンを導入できます。

必要な依存関係をインストールする方法はいくつか提案されているのですが、今回は、最新のstable版Chromeをパッケージ管理ツール経由でダウンロードし、依存関係だけ残してChrome本体は削除するアプローチを採用しました。

Dockerfile
FROM python:3.12

# Chromeの依存関係をインストール
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update \
    && apt-get install -y --no-install-recommends google-chrome-stable \
    && apt-get remove -y google-chrome-stable \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY test.py .

CMD ["python", "test.py"]
requirements.txt
selenium==4.11.0
test.py
from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--headless')

# ChromeとChromeDriverのメジャーバージョンを指定(ここでは120)
options.set_capability('browserVersion', '120')

driver = webdriver.Chrome(options=options)
### 何らかの処理 ###
driver.quit()

コンテナを起動してスクリプトが実行されると、バージョン120のChromeとChromeDriverがインストールされます。

Chrome for Testing

Selenium Managerを使用しない場合、Chrome for Testingの利用可能バージョン取得APIを使って、必要なバージョンのChromeとChromeDriverをインストールします。この場合も、依存関係は別途インストールする必要があります。

Dockerfile
FROM python:3.12

# Chromeの依存関係とunzip、jqをインストール
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update \
    && apt-get install -y --no-install-recommends google-chrome-stable unzip jq \
    && apt-get remove -y google-chrome-stable \
    && rm -rf /var/lib/apt/lists/*

# ChromeとChromeDriverのメジャーバージョンを指定(ここでは120)
ARG MAJOR_VERSION=120

# 指定したメジャーバージョンで最も新しいバージョンのChromeとChromeDriverをダウンロード
RUN wget -q -O versions.json https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json \
    && LATEST_MINOR_VERSION=$(jq -r --arg MAJOR_VERSION "$MAJOR_VERSION" '.versions | map(select(.version | startswith($MAJOR_VERSION))) | map(.version) | sort_by(split(".") | map(tonumber)) | last' versions.json) \
    && echo "LATEST_MINOR_VERSION is $LATEST_MINOR_VERSION" \
    && mkdir -p /opt/chrome \
    && wget -q -O /opt/chrome/chrome-linux64.zip $(jq -r --arg LATEST_MINOR_VERSION "$LATEST_MINOR_VERSION" '.versions | map(select(.version == $LATEST_MINOR_VERSION)) | .[0].downloads.chrome | map(select(.platform == "linux64")) | .[0].url' versions.json) \
    && wget -q -O /opt/chrome/chromedriver-linux64.zip $(jq -r --arg LATEST_MINOR_VERSION "$LATEST_MINOR_VERSION" '.versions | map(select(.version == $LATEST_MINOR_VERSION)) | .[0].downloads.chromedriver | map(select(.platform == "linux64")) | .[0].url' versions.json) \
    && unzip /opt/chrome/chrome-linux64.zip -d /opt/chrome \
    && unzip /opt/chrome/chromedriver-linux64.zip -d /opt/chrome \
    && rm /opt/chrome/*.zip versions.json

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY test.py .

CMD ["python", "test.py"]
requirements.txt
selenium==4.10.0
test.py
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--headless')

# パスを指定
options.binary_location = '/opt/chrome/chrome-linux64/chrome'
service = Service(executable_path='/opt/chrome/chromedriver-linux64/chromedriver')

driver = webdriver.Chrome(service=service, options=options)
### 何らかの処理 ###
driver.quit()

コンテナにはChromeとChromeDriverが格納されています。

参考資料

Chromeの依存関係の導入方法については、下記を参考にさせていただきました。
https://github.com/GoogleChromeLabs/chrome-for-testing/issues/121#issuecomment-2089418937
Seleniumの利用方法については、下記の記事を参考にさせていただきました。
https://gammasoft.jp/support/selenium-with-batteries-included

レスキューナウテックブログ

Discussion