M1MacのDockerでSelenium使う方法（＆使いたくてハマった話😵‍💫）

## DockerでSeleniumを使いたい！

「PythonでWebページ解析したいときにはSeleniumとBeautifulSoupを使うのが有名なんですね（？）」っていうレベル感かつ「Dockerもしっかり理解していない」私ですが、「Seleniumちょっとサクッと試してみるか、ライブラリimportすればすぐ使えるんでしょ😙？とりあえずDockerで動かしたいな。」くらいの感じで試したら、全くサクッとできませんでした...

解決策というほどでもありませんが、解決策とハマった内容の共有です！

**※ 上記のようなレベル感なので、以下、間違い含んでいたり他にも解決策があるものと思われますが、ご容赦ください🙇‍♂️**

※2023-11-02 追記
以下の記事では「なぜM1 MacのDockerでSeleniumが動かないのか」が、詳細にまとめていただいていたので、参考にリンク貼らせていただきます！

https://qiita.com/mejiro03/items/76f7080b3ab25cbee8e4

## 解決策： docker-seleniarmのイメージを利用する！

解決策は以下のとおりです！
Selenium公式のDockerイメージからForkされたARMチップ向けのイメージ（下記リンク）を利用すれば、サクッと（？）動かすことができます！
※まだ実験中イメージのようです。

https://github.com/seleniumhq-community/docker-seleniarm

### Docker関連のファイル
VSCodeのDev Containerを使う前提で以下３つを用意しました。
SeleniumサーバーとPython環境の2つのコンテナが立ち上がります。
Python3.10でPoetryがインストールされたコンテナです。

- devcontainer.json
- docker-compose.yaml
- Dockerfile

```json:devcontainer.json
{
	"name": "seleniarm-poetry",
	"dockerComposeFile": "docker-compose.yml",
	"service": "app",
	"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
	"customizations": {
	  "vscode": {
		"extensions":["ms-python.python", "njpwerner.autodocstring"]
	  }
	}
}
```

```yaml:docker-compose.yaml
version: '3'
services:
  selenium:
    container_name: seleniarm
    image: seleniarm/standalone-chromium:latest
    ports:
      - 4444:4444
    shm_size: "2gb"
  app:
    container_name: poetry-for-seleniarm
    build:
      dockerfile: .
    volumes:
      - ../..:/workspaces:cached
    environment:
      SELENIUM_URL: http://selenium:4444/wd/hub # SELENIUM_URLを環境変数として設定
    tty: true
    depends_on:
      - selenium
```

```Dockerfile:Dockerfile
FROM mcr.microsoft.com/devcontainers/base:jammy

ARG DEBIAN_FRONTEND=noninteractive
ARG USER=vscode

RUN DEBIAN_FRONTEND=noninteractive \
    && apt-get update \ 
    && apt-get install -y build-essential --no-install-recommends make \
        ca-certificates \
        git \
        libssl-dev \
        zlib1g-dev \
        libbz2-dev \
        libreadline-dev \
        libsqlite3-dev \
        wget \
        curl \
        llvm \
        libncurses5-dev \
        xz-utils \
        tk-dev \
        libxml2-dev \
        libxmlsec1-dev \
        libffi-dev \
        liblzma-dev

# Python and poetry installation
USER $USER
ARG HOME="/home/$USER"
ARG PYTHON_VERSION=3.10
# ARG PYTHON_VERSION=3.10

ENV PYENV_ROOT="${HOME}/.pyenv"
ENV PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${HOME}/.local/bin:$PATH"

RUN echo "done 0" \
    && curl https://pyenv.run | bash \
    && echo "done 1" \
    && pyenv install ${PYTHON_VERSION} \
    && echo "done 2" \
    && pyenv global ${PYTHON_VERSION} \
    && echo "done 3" \
    && curl -sSL https://install.python-poetry.org | python3 - \
    && poetry config virtualenvs.in-project true
```
※上記Dockerfileは以下の`python3-poetry-pyenv`のdevcontainerテンプレをそのまま利用しています。
https://github.com/Standard-IO/devcontainers-templates

### 使い方イメージ
ざっくり利用方法のイメージは以下のような感じです！

```python:test.py
from selenium import webdriver
from bs4 import BeautifulSoup
import os
import time


# ブラウザの設定
options = webdriver.ChromeOptions()
driver = webdriver.Remote(
    command_executor=os.environ["SELENIUM_URL"], # 環境変数のSELENIUM_URLを読み込む
    options=options,
)

# ブラウザでURLにアクセスし、レンダリングを待機してからHTMLを取得
driver.get('解析対象のURL')
time.sleep(5)
html = driver.page_source

# BeautifulSoupを使用してHTMLを解析
soup = BeautifulSoup(html, "html.parser")

# 解析内容 〜〜〜〜〜

driver.quit()
```

## ハマった話

ここからは蛇足です！失敗した流れです。
前述の通り、知識不足故に間違いあるかもしれませんので、生暖かい目でよろしくお願いします！

### DockerにChromeをインストールしてSeleniumを使う

まず始めに試みたのが、「DockerにChromeをインストールしてSeleniumを使う」です。
しかし、Chromeのインストールがうまくいかないではありませんか！
（間違っているかもですが）「ARMチップLinux用のChromeが配布されていない」からという結論に至りました。

Dockerのプラットフォームを指定してコンテナを起動すればいいのかなと`platform: linux/x86_64`とか`　--platform=linux/amd64`あたりを試したがだめでした。

### docker-seleniumを利用する

Seleniumが公式で配布しているDockerイメージがあることに気がついたのでそちらを利用することにしました。

https://github.com/SeleniumHQ/docker-selenium

まずは、何も考えずにコンテナを立ち上げようとしましたが、Seleniumのコンテナが立ち上がりませんでした。
理由はChromeの時とおなじでプラットフォームがあっていないかららしい。

そこで、docker-compose.yamlで`platform: linux/x86_64`を指定トライしたところ、無事にコンテナが立ち上がりました！
しかし、いざ、コードを実行しようとするとエラーが発生してだめでした。
こちらも、恐らくプラットフォーム問題なのだと思います。

### docker-seleniumに気がつく

もう一度、docker-seleniumのREADMEをちゃんと読むことにしました。

そうすると、以下の通りARM用の案内があるではありませんか！（始めにREADMEしっかり読むの大事😭）

https://github.com/SeleniumHQ/docker-selenium#experimental-mult-arch-aarch64armhfamd64-images

早速こちらで案内されている`docker-seleniarm`を利用することで解決しました。


## 振り返り

「公式ドキュメント読むべし」とよく言われますが、公式ドキュメントやREADMEを読むのが、急がば回れの近道かもしれないなと思った次第です。


## 参考にさせていただいた記事

https://bgtu-techblog.com/2022/08/06/selenium%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%9Fdocker%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%9F%E3%81%84/

https://qiita.com/ha_ru/items/86dfaae4c92e4a7be13f

https://gihyo.jp/admin/serial/01/ubuntu-recipe/0662

https://tech-lab.sios.jp/archives/28840

https://datascience-beginer.com/docker_selenium/