docker × Locust × Selenium

## はじめに

1. そもそも、pythonなんてほとんど触ったことない
2. dockerは普段作ってもらったものを共有されるので、自分で作る経験が浅い<BR>
（自分の開発のためにシステム情報貰って同じ環境作ったくらいの知識）
3. locustなにそれおいしいの？
4. 負荷試験やったことないんですけど...（テスト項目とかサンプルデータとか作ったことある程度）
5. seleniumはC#で使ったことあるはず...うろ覚え
6. （＋圧力）１か月かからずササっとできるよね...にっこり

これは、、、私、死亡フラグでは...:(；ﾞﾟ''ωﾟ''):...
とにかくやるしかないので、紆余曲折あり、困って調べたことだけ羅列しておきます
まだ、全然のみこめていない部分が多いので間違ってたらごめんなさい


## 必要なもの

■ Docker

**DockerDesktop**
https://www.docker.com/products/docker-desktop

:::note warn
前の記事でwindows7のときは、DockerToolbox × vagrantでしたが
windows10にアップグレードしたときにDockerDesktopに変わりました
:::

■ Docker Compose

docker-compose.ymlは、基本的にはlocustのドキュメント通りに書いているだけなんだけど
locustの他にもいろいろインストールしたり環境設定したいのでDockerfileは一番最後に書きます

**Running in Docker**
https://docs.locust.io/en/stable/running-locust-docker.html

**locust docker image**
https://hub.docker.com/r/locustio/locust

:::note info
docker pull するとログに @sha256:~ っていうハッシュが表示されるので
後でDockerfileに記載して使います
:::

■ locust-plugins使って、seleniumと連携

locustのドキュメントに一行だけそっと記載されていたのですが
これを見つけるのに時間がかかりました...Google先生教えてくれないんだもん...

> For more examples of user types, see locust-plugins (it has users for WebSocket/SocketIO, Kafka, Selenium/WebDriver and more)

https://docs.locust.io/en/stable/testing-other-systems.html#example-writing-a-grpc-user-client

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106779/84118c3d-2e0e-aa02-0a10-b6c31e3ebfb8.png" width="75%">

**locust-plugins**
https://github.com/SvenskaSpel/locust-plugins

**webdriver**
https://github.com/SvenskaSpel/locust-plugins/blob/master/locust_plugins/users/webdriver.py
※pluginsのwebdriverのソースは、docker build時にインストールするので記載の確認するだけ

**webdriver_ex**
https://github.com/SvenskaSpel/locust-plugins/blob/master/examples/webdriver_ex.py
※必要なのがseleniumなので、webdriverのサンプルを見ていい感じにソースを書きます
サンプルソース見て何とかしてね！！！って感じですね...w

ここで！！！！この記載に気づくのにまた時間がかかりました...
> You need to start selenium server first:
> Download it from https://www.seleniumhq.org/download/ and run it by executing:
> java -jar selenium-server-4.0.0-beta-4.jar standalone
> Also, make sure you have installed chromedriver first. On macOS you would do: brew install --cask chromedriver

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106779/a20cad2d-819e-4b81-2e06-7b355563d8be.png" width="75%">

スタンドアロンでselenium serverを動かしてね（ﾃﾍﾍﾟﾛｯ

dockerにjavaとselenium serverのダウンロードが必要ですね...orz
あとはchrome使うので、chrome本体とchromedriver（＋chromedriverのパス設定）

:::note alert
現状わかっている範囲で、selenium-server-4.0.0-beta-4.jar だとlocustで並列実行したときに
「Could not start a new session. New session request timed out.」
のエラーで３ユーザーほどでseleniumブラウザが起動できなくなります

いろいろ調査した結果、最新のバージョン
https://githubmemory.com/repo/SeleniumHQ/docker-selenium/issues/1331

4.0.0-rc-1-prerelease-20210713 ← 2021年07月13日にプレリリースした版で解消されているかもしれませんが
昨日わかった話なので、現在進行形で調査中です...
知っている人いたら教えてください :bow_tone1: 
:::

■ Dockerfile

Google先生にいろいろ聞いて紆余曲折しましたが、最終こうなりました

```Dockerfile
FROM locustio/locust@sha256:78148a8b40d012f29d7f274a72e347552e373d740275b7e2f455e70e11c4e9b1
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less psmisc

RUN sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN apt update
RUN apt install google-chrome-stable -y
RUN apt install openjdk-11-jdk -y

RUN wget https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.0.0-beta-4/selenium-server-4.0.0-beta-4.jar

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install locust-plugins
RUN pip install webdriver-manager
RUN pip install chromedriver-binary-auto

ENV PATH $PATH:/usr/local/lib/python3.8/site-packages/chromedriver_binary
RUN echo $PATH

#imageで設定されているエントリーポイントをリセット
ENTRYPOINT [""]
```

+ FROM にlocust imageをdocker pull したときに出たログの**Digest**

https://docs.docker.jp/engine/reference/commandline/pull.html

+ 一応日本語とか日本時刻に変更
+ 各種update
+ docker execで入ったとき用に使うコマンド類 vim less
+ selenium のプロセスを落とすコマンドに使われている psmisc(killall) ※dockerに入ってないと思ってなくてコレもハマった...
+ chrome安定の最新版　※seleniumにバージョン指定されることもあるので指定のバージョンで
+ java　※javaコマンドが使えれば何でも良さそうだったのでとりあえず11にしておいた
+ selenium-server　※locust-pluginsに明記されていたバージョンと同じもの
+ pipの更新と必要なpythonのライブラリ
+ chromedriverへのパス　※使用するlocust imageがpython3.8を使用していたのでこのパスですがパスは適宜変えてね
+ locust image内で ENTRYPOINTを "locust" に設定されていたので一旦クリア

locust imageで使用されているDockerfile
https://github.com/locustio/locust/blob/master/Dockerfile
※これを上書きするような形になる？んだと思う...あまりわかってない...

いろいろ起動時にコマンドを実行する方法があると思うんですが

- 他人に渡してほとんど手を加えずそのまま実行できること
- 負荷テストにちょっと使うだけだから「なるべくファイルを増やしたくない」

という理由で、今回は、docker-compose.ymlで起動直後にコマンド実行する方向で調整しました
この辺の方法はsh書いたりしてもいいとは思うのでお好きにどうぞ

■ docker-compose.yml

```docker-compose.yml
version: '3'

services:
  master:
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    container_name: locust_master
    ports:
      - "8089:8089"
    volumes:
      - ./:/mnt/locust
    command: >
      sh -c '
        java -jar selenium-server-4.0.0-beta-4.jar standalone &
        locust -f /mnt/locust/locustfile.py --master -H http://master:8089
      '

  worker:
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    container_name: locust_worker
    volumes:
      - ./:/mnt/locust
    command: >
      sh -c '
        java -jar selenium-server-4.0.0-beta-4.jar standalone &
        locust -f /mnt/locust/locustfile.py --worker --master-host master
      '
```

1. ほぼ公式と同じだけど、Dockerfileがあるのでそれを使うように変更
2. docker起動後すぐに終了しちゃったので、ttyをtrueに
3. 起動直後(locust起動前)に、seleniumserverを立ち上げておく

## 最後に

途中ちょっと書きましたが、まだ負荷テストを行えるだけのブラウザ数を同時に起動できていない（最高3ユーザー）ので
まだまだ、設定とか変わる可能性がありますが、忘れないようにメモ書きしているだけだと思ってください...(;´∀｀)

```Number of users``` 3
```Spawn rate``` 3

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106779/891fd223-3503-9f80-75b0-5a2a3d63e8ed.png" width="75%">


全部ではないにせよ、どこかで躓いている人がいたら、参考になれば幸いです
あと、間違ってる箇所あったら教えてください

早く解決するといいな...