Chrome for Testingを使ったSelenium on Dockerの環境構築

## 背景

PythonとSeleniumでChromeブラウザを操作する実行環境をDockerで作成する場合、コンテナ内にPython、Chrome、ChromeDriverをそれぞれインストールするのが一般的かと思います。
とはいえお試しで使ってみたい、簡単なWebスクレイピングだけやりたいといった場合は１つのコンテナで済むような簡単な構成にしたいところです、また、ChromeとChromeDriverの互換性問題についても面倒なので気にせず構築できると嬉しいです。

## 本記事の目的

以上を踏まえて環境構築が簡単でなるべく軽量なDockerコンテナを作成してみました。
定型作業の自動化やWebスクレイピングの範囲であれば、この構成で事足りるかと思います。

## Dockerfileによる環境構築

ブラウザやライブラリのバージョンは以下の通りです。

||バージョン|
|:-:|:-:|
|Python|3.12|
|Selenium(Pythonライブラリ)|4.25|
|Chrome for Testing(ブラウザ+WebDriver)| 130.0.6723.91|

以下はDockerfileの中身です。

```Dockerfile
# Chrome for TestingのDL＆展開用にubuntuのイメージを使う
FROM ubuntu:22.04 AS downloader

RUN apt-get update && apt-get install -y curl unzip

RUN curl -O https://storage.googleapis.com/chrome-for-testing-public/130.0.6723.91/linux64/chrome-linux64.zip && \
    unzip chrome-linux64.zip

# Python実行用
FROM python:3.12-slim

# 前のイメージで展開した資材をコピー
COPY --from=downloader /chrome-linux64 /chrome-linux64

# Pythonライブラリのインストールしてキャッシュ削除
RUN pip install --upgrade pip && \
    pip install selenium==4.25.0 && \
    pip cache purge

# ブラウザを動かすためのパッケージをインストール
RUN apt-get update && \
    apt-get install -y libasound2 libgtk-3.0 libgbm1 libnss3 && \
    apt-get clean
```

動作確認用のサンプルコードです。作成したコンテナ上で実行してみてください。

```python
from selenium import webdriver
from tempfile import mkdtemp
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()

options.binary_location = '/chrome-linux64/chrome'
options.add_argument("--headless=new")
options.add_argument('--no-sandbox')
options.add_argument("--disable-gpu")
options.add_argument("--single-process")
options.add_argument("--disable-audio-output")

chrome = webdriver.Chrome(options=options)
chrome.get(<アクセス先URL>)

res = chrome.find_element(by=By.XPATH, value="//html").text

print(res)
```
### 解説

ポイントはChromeのテスト用ブラウザであるChrome for Testingを使う点で、ChromeとChromeDriverが一体となっているのでバージョン互換性を気にする必要がなくなります。
Chrome for Testingについてはこちらの記事で分かりやすくまとめられています。
[Chrome for Testing で自動テストを手元で簡単に動かせるようにした-Qiita](https://qiita.com/yurizono/items/94e5b6ce61ff8ddcd9ee)

バイナリのダウンロード先は[Chrome for Testing availability](https://googlechromelabs.github.io/chrome-for-testing/)で確認できます。古いバージョンのリンクは[our JSON API endpoints](https://github.com/GoogleChromeLabs/chrome-for-testing?tab=readme-ov-file)に書いてあります。

#### つまずきポイント

##### 依存パッケージ

今回ベースとしたPythonイメージにはChrome for Testingの依存パッケージが入っておらず、そのままChrome for Testingを実行すると必要なライブラリが足りずエラーが発生します。なので不足しているパッケージを入れてあげればいいのですが、依存パッケージリストのような情報を見つけられず、以下のサイトを参考に解決しました。
[Puppeteerがnodeコンテナで動かなかったから動かした-White Box技術部](https://seri.hatenablog.com/entry/2020/10/04/012459)
Pupperteer（Chromeブラウザを操作するNode.jsライブラリ）が必要というわけではなく、エラー内容がほぼ同じだったので紹介されている解決策を試したところ解決してしまった、という結果です。。。
依存関係を解決するためchromeを入れる方法もあるようですが、とりあえずサンプルコードは動いたので今回はこれで良しとしています。

## まとめ

以上、Chrome for Testingを使ったSelenium実行環境の構築についてでした。簡単なWebスクレイピングや自動テストなどを試す際参考になれば幸いです。

## 参考文献
1. [Chrome for Testing: reliable downloads for browser automation-Chrome for Developers](https://developer.chrome.com/blog/chrome-for-testing?hl=ja)
2. [Chrome for Testing で自動テストを手元で簡単に動かせるようにした-Qiita](https://qiita.com/yurizono/items/94e5b6ce61ff8ddcd9ee)
3. [Chrome for Testing availability](https://googlechromelabs.github.io/chrome-for-testing/)
4. [our JSON API endpoints-Github](https://github.com/GoogleChromeLabs/chrome-for-testing?tab=readme-ov-file)
5. [Puppeteerがnodeコンテナで動かなかったから動かした-White Box技術部](https://seri.hatenablog.com/entry/2020/10/04/012459)