概要
以下の図のような E2E テスト環境基盤 を構築しました。
これは以下からコードを clone し bash deploy.sh を実行すると環境が出来上がったりします。
※docker, docker-compose が使えることが前提です
なんでこんな面倒な構成をするんだという所もありますが、とりあえず環境を作ってみたという所が大きいです。
いつの間にやら docker-compose の書き方も変わったりしていたのでいい勉強になりました。
ということでこの テスト環境基盤の説明・デプロイ方法と、 docker-compose.yml の書き方を記事にしました。
ただし内容が多いので2つの記事に分けています。具体的には下記のようになっています。
この記事に書かれていること
- docker-compose の記載方法の説明
- version
- services
- image
- build
- context
- dockerfile
- args
- ports
- volumes
- links
- depends_on
- environment
- まとめ
もう一つの記事に書かれていること
Selenium, Jenkins, Ruby(Capybara) の E2E テスト環境基盤を Docker で構築したときの知見のまとめ(環境編)
-
Selenium,Ruby Script,JenkinsによるE2Eテスト環境基盤の説明 - 上記コンテナ達のデプロイ方法
- 上記
Jenkins(docker)の起動・初期設定・ジョブの実行 - まとめ
という事でこちらは 書き方編 になります。宜しくお願いします。
docker-compose の記載方法の説明
はじめに
docker-compose.yml で登場する image は以下の3種類です。
( tag を指定しているのは tag の upgrade で動かなくなるのを避けるためです)
- selenium
- selenium/standalone-firefox-debug:3.0.1
- ruby
- ruby:2.4
- jenkins
- jenkins:2.32.1
これは docker-compose.yml に以下のように記載され分割されています。
version: '2.0'
services:
selenium:
#...
ruby:
#...
jenkins:
#...
docker-compose up -d を実行すれば docker-compose.yml を読み込み、各イメージを作ってくれる訳です。
さて、今回 E2Eテスト環境基盤の構築のために作成した docker-compose.yml は以下のようになっています。
これをもとに記載方法を説明していきます。
version: '2.0'
services:
# for e2e selenium
selenium:
image: selenium/standalone-firefox-debug:3.0.1
container_name: selenium
restart: always
ports:
- 5900:5900 #VNC
expose:
- 4444 #selenium
volumes:
- ./ruby/download:/home/seluser # for download file
# for scripts
ruby:
build:
context: ./ruby
dockerfile: Dockerfile
args:
- password=${DOCKER_PASSWORD}
container_name: ruby
restart: always
depends_on:
- selenium
volumes:
- ./ruby:/usr/src/app
environment:
- SELENIUM_HOST=${SELENIUM_HOST}
- SELENIUM_PORT=${SELENIUM_PORT}
# for execute tool
jenkins:
build: ./jenkins/
container_name: jenkins
restart: always
ports:
- "18080:8080"
- "50000:50000"
volumes:
- ./jenkins:/var/jenkins_home
environment:
- DOCKER_PASSWORD=${DOCKER_PASSWORD}
version: 全てを取り締まる全知全能なるもの
version: '2.0'
version は docker-compose.yml の記載が version 1 のものか version 2 のものかを判定するために使われます。
今回は複数のコンテナを services という項目内でまとめています。これは version 2 の記載方法になります。
例えばこれを version "1" とかにするとエラーになります。
一番頭に書いておく大切なやつです。
services: コンテナを統べる母なるもの
services:
selenium:
#...
ruby:
#...
jenkins:
#...
今回のように複数のコンテナを同時に起動したり、削除したりしたいときは、この services を使うと実現ができます。
こうしてまとめていると docker-compose up を実行すると selenium, ruby, jenkins をそれぞれコンテナ化してくれます。
またコンテナを削除をするときもまとめて削除をしてくれたりします。
image: 教えよ、汝の名を
services:
selenium:
image: selenium/standalone-firefox-debug:3.0.1
#...
image にはどの Docker image を使用するかを記載します。
ここで記載したイメージからコンテナを作成するのでとっても重要なものです。
例えば上記 selenium の例では selenium/standalone-firefox-debug という名前の付いたイメージの 3.0.1 のタグを付いたものを取得します。
タグというのはおおざっぱに言うとイメージの version のようなものです。
例えば ruby のイメージであれば ruby:2.3 とすると Ruby の version が 2.3 のイメージを取得できます。
タグは指定しなければ latest という扱いになり、 latest (最新) というタグのついたイメージが取得されます。
build: 創りしは新たな命、吹き込むは次への希望
services:
ruby:
build:
context: ./ruby
dockerfile: Dockerfile
args:
- password=${DOCKER_PASSWORD}
build は コンテナを作成するときの Dockerfile を指定するオプションです。
context や args の子オプションを持ちますがこれらは省略可能です。
例えば下記のように記載するとカレントディレクトリ(docker-compose.yml のあるディレクトリ)の Dockerfile という名前のファイルを見つけに行きます。
services:
ruby:
build: .
context には Dockerfile が置かれているディレクトリの場所を記載します
dockefile には イメージを build する際のファイルを指定します。
args には Dockerfile に渡す引数を記載します。今回はコンテナ作成時の root ユーザに設定するパスワードを passwaord という名前の引数で渡しています。参考
よって今回私が記載した ruby のイメージは ./ruby/Dockerfile に $DOCKER_PASSWORD を引数として渡したイメージを作っているということです。
container_name: これは運命。其方を示す無二なるもの
services:
selenium:
container_name: selenium
container_name でコンテナの名前を指定することができます。
通常コンテナを作成するときは、ランダムに友達のような名前がコンテナに割り振られます。
その名前を自分の好きな名前に指定ができるオプションです。
Docker のコンテナの名前はとても大きな意味を持ちます。
例えばコンテナの名前は必ず一意で無ければなりません。これは様々な操作やオプション設定の際に名前を使用することがあるからです。
(これ、ちょっと前の version だと使えなかったんですよねぇ……)
restart: 不死なるもの。それは栄光か地獄か
services:
selenium:
restart: always
restart オプションを付けるとコンテナを自動で起動することができます。
今回は常に再起動をする always を指定していますが、回数や再起動をしないオプションも設定できます。
例えばホスト側を再起動した際に、通常コンテナは再起動しません。
docker ps では見えなくなるので消えたかのように思いますが docker ps -a とすると見えます。
眠っちゃってるんですね。
このときにホスト側が起動(Dockerが起動)したときに、自動でコンテナを起動できるので便利なオプションです。
ただしコンテナがエラーを起こして起動ができなかったときでも、 always は健在です。
こんな時はコンテナは起動と停止を繰り返すリビングデッドみたいになります。
ports: 深淵をのぞく時、深淵もまたこちらをのぞいているのだ
services:
selenium:
ports:
- 5900:5900
ports は一言でいうとポートフォワディングです。<hostのPort>:<containerのPort> という記載ルールでポート番号を記載します。
**通常コンテナはポートを外部に公開しません。**外部からコンテナ内部の特定のポートに接続をしたいときはこの設定を入れましょう。
ただしこの設定を入れると、ホストの外からもコンテナへ接続ができる状態にもなり、セキュリティ的に危険にさらされる可能性があります。
ポートフォワディングをするときはセキュリティ的に大丈夫かという観点を持ってやりましょう。
どうしてもセキュリティに関わるものをポートフォワディングしないといけないときは、ホスト側のポートの値を別の物にするのも手です。
expose: モーゼは海を絶ち示した。我らの道はここなり
services:
selenium:
expose:
- 4444
expose は指定したポートをコンテナの外へ公開するオプションです。
ただし ports とは異なり、公開に制限があります。
例えば上記の設定では selenium の 4444 ポートに接続できるのはホストと他のコンテナのみになります。
接続の際はコンテナのIPを取得してポートを指定する必要があります。
ports に比べて使い勝手がやや落ちるものの、セキュアな設定となります。
links, depends_on: 縁を紡ぎ虹を架ける。其方は独りではない
services:
selenium:
#...
ruby:
depens_on:
- selenium
links, depends_on はコンテナ間の接続のためのオプションで、ほぼ同じ意味合いです。
例えば上記のように ruby と selenium を接続させます。
こうすると ruby コンテナから selenium という名前で selenium コンテナの IP を参照することができるようになります。
これは ruby コンテナの /etc/hosts に記載が追加されるためです。
こうしておけば ruby コンテナから ping を以下のように飛ばしたりすることもできます。
ping selenium
また、 links と depends_on の違いですが、 depends_on を指定していると、コンテナの作成順序をコントロールすることができるようになります。
つまり上記の設定は selenium のコンテナが作成された後に ruby のコンテナを作成し、そして接続の関係を作るというオプションになります。
volumes: 同じ月を眺めていると思えば、孤独な闇夜も恐れずにすむ
services:
jenkins:
volumes:
- ./jenkins:/var/jenkins_home
volumes オプションを使えばホストとコンテナ間で、指定したディレクトリを共有することができます。
これにより以下の3つが実現されます。
- 1.コンテナに接続しなくても、ホスト側で共有ディレクトリに行った編集がコンテナに反映される
- 2.コンテナに接続しなくてもコンテナのファイルをホスト側からすぐに参照できる
- 3.コンテナを廃棄した後にもデータがホスト側に残る
上記の jenkins の volumes 設定は上記 3 のために入れています。
これをすることでもし jenkins のコンテナを再作成しても、データを残すことができます。
※ 通常はコンテナを破棄すると中のデータもすべて削除されます
よって jenkins のコンテナで設定したジョブや設定をいつまでも残すことができます。
逆に言うと本当に初期化したいときは volumes で設定しているディレクトリのファイルをホスト側で削除したりする必要がありますね。
environment: 活け、其方の名は……ノビタニアン!
services:
ruby:
environment:
- SELENIUM_HOST=${SELENIUM_HOST}
- SELENIUM_PORT=${SELENIUM_PORT}
environment に記載を入れると、イメージからコンテナを作成するときに、環境変数をセットすることができます。
ちなみに docker-compose.yml でホスト側で使っている環境変数を使いたいときは $VALUE か ${VALUE} でできます。
まとめ
-
Selenium+Ruby Script+Jenkinsによる E2E自動テストの環境をDockerにて構築しました。 - 構築には
docker-composeを使い一元的に各コンテナを管理するようにしました。 - この記事には
docker-composeの詳しい書き方を記載しました。
もしこの基盤の詳細やデプロイ方法を知りたいという方は下記をご参照ください。
Selenium, Jenkins, Ruby(Capybara) の E2E テスト環境基盤を Docker で構築したときの知見のまとめ(環境編)
