Docker を活用して即座に Python Selenium 実行環境を作る


## 概要

各自の物理 PC に対して、セットアップ手順を提示して Python Selenium 環境を準備してもらおうとしたが、
(お決まりの) 次の問題が多発した.

・構築手順ミス
・apt パッケージの不整合で正しく環境が構築できない

そこで手順を簡単にするために Docker を用いた Python Selenium 実行環境を提示したので、書き残しておく.


## 詳細

### 概念図

下図のような環境を作る.

![sel.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/1b8ba343-b57d-1e4d-2b2b-f455e91c3e3f.jpeg)


### 物理ホスト

|項目|値|補足事項|
|:--|:--|:--|
|OS|Ubuntu 18.04| 別 OS でも問題無し |
|Dockerエンジン|19.03| (導入手順は省略する) |


### 構築する Docker イメージ・コンテナ

|項目|値|補足事項|
|:--|:--|:--|
|Dockerイメージ|python:3.8.8-buster||
|Selenium| バージョン未確認 ||
|Chrome Driver|最新版|動的に最新版を入手するようにしている|
|Google Chrome ブラウザ|最新 Stable バージョン||
|Xvfb| バージョン未確認 | 仮想ディスプレイ |
|日本語フォント| バージョン未確認 | いわゆる「[豆腐](https://michinarinukazawa.github.io/TofuFont/html/)」対策である|



## 構築手順

### 1. 永続ボリューム「./app/」を作成する

物理ホスト側での操作である.
./app 以下に Python コードを実装していく.

```
$ mkdir ./app
```

### 2. Dockerfile を作成する

```dockerfile
FROM python:3.8.8-buster

WORKDIR /usr/src/app
 
# Webブラウザ「google-chrome」をインストールする。
# 当然 google-chrome のバージョンに応じて手順は異なるので、随時手順を確認すること.
RUN wget --no-check-certificate https://dl-ssl.google.com/linux/linux_signing_key.pub
RUN apt-key add linux_signing_key.pub
RUN sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main " >> /etc/apt/sources.list'
RUN apt-get update -y
RUN apt-get install google-chrome-stable -y
 
# Chrome ドライバをインストールする (常に最新版を取得する)
RUN apt-get install -yqq unzip curl -y
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/
 
# pip を使って selenium パッケージをインストールする
RUN pip install --upgrade pip
RUN pip install selenium
 
# 日本語フォントをインストールする
ENV LANGUAGE ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
RUN apt-get install -y --no-install-recommends locales && \
    locale-gen ja_JP.UTF-8 && \
    apt-get install -y --no-install-recommends fonts-ipafont
 
# 仮想ディスプレイソフト Xvfb をインストールする
RUN apt-get install xvfb -y
 
# GUI 起動確認で xeyes があると便利なのでデバッグ用途で x11-apps をインストールする
RUN apt-get install x11-apps -y
```

### 3. Docker イメージビルドをする

物理ホスト側での操作である.

```bash
$ docker image build -t myselenium:001 .
```

無事にビルドが済めば、次のようにイメージが存在しているはずである.

```bash
$ docker images
REPOSITORY    TAG            IMAGE ID       CREATED          SIZE
myselenium    001            cd8007e49f7a   40 seconds ago   1.47GB
```

### 4. Docker コンテナを起動させる

コンテナ名を「`my001`」とする.
なお、下記設定を使用する・しないは各自の環境に合わせること.
・`--net host`
・`-e DISPLAY=$DISPLAY`


```bash
$ docker run -it -d --name my001 \
               --mount type=bind,src=`pwd`/app,dst=/usr/src/app \
               -e DISPLAY=$DISPLAY \
               --net host \
               myselenium:001
```

無事に起動すれば、次のようにコンテナが存在しているはずである.

```
$ docker ps
CONTAINER ID   IMAGE           COMMAND     CREATED              STATUS              PORTS     NAMES
5349528d14d2   myselenium:001  "python3"   About a minute ago   Up About a minute             my001
```


### 5. 実行したいコードを作成する

物理ホスト上での操作である. ここでは ./app/sample.py として Selenium 操作をするコードを書いたものとする.

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
  
from __future__ import print_function
import sys; sys.dont_write_bytecode = True
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import csv, time, os, re, subprocess, tempfile, shutil, json

以下略
```


### 6. 実行する

物理ホスト上での操作である.
コンテナ「my001」にログインして、コンテナ内の /app/sample.py を実行している.

```bash
$ docker exec -it my001 bash -c 'python sample.py'
```

この後、selenium を使った実装を進めれば良い.

　

以上.