こんにちは、サイオステクノロジー技術部 武井です。全2回シリーズ「コンテナ時代のDevOps」第2回目は、Azure Web Apps for Containers + Docker + Jenkins + SeleniumでCI/CDを実践してみたいと思います。
※全シリーズの記事一覧はこちら
- コンテナ時代のDevOps 〜Azure Web Apps for Containers + Docker + Jenkins + SeleniumでイマドキのCI/CDをやってみる [理論編]〜
- 今回はこちら → コンテナ時代のDevOps 〜Azure Web Apps for Containers + Docker + Jenkins + SeleniumでイマドキのCI/CDをやってみる [実践編]〜
- 1 CI/CDの構成
-
2
実際にやってみる
- 2.1 Jenkinsのインストール
- 2.2 Azure Container Registryの設定
- 2.3 Hello WorldアプリケーションのDockerイメージ作成
- 2.4 Hello WorldアプリケーションのソースコードのGitHubへのpush
- 2.5 Web App for Containersの設定
- 2.6 SeleniumによるUIテスト自動化スクリプトの作成
- 2.7 パイプラインによる自動化スクリプトの作成
- 2.8 Jenkinsによるメール通知の設定
- 2.9 GitHubのwebhookの設定
- 2.10 Azure Container Registryのwebhookの設定
- 2.11 試しにやってみよう!!
- 3 最後に
CI/CDの構成
本章では、今回、実践を行うCI/CDの構成をご説明します。
上図のそれぞれのフェーズの詳細を以下にご説明します。
※下記の数字は上図の数字に対応しております
(1) 開発エンジニアがソースをコミットします。
これは、開発エンジニアがバージョン管理システム(今回はGitHub)にソースコードをコミットする処理です。CI/CDのライフサイクルの起点はこの処理になり、人の手がかかるのはこの処理のみになります。これ以降の処理は、Jenkinsにより全て自動化されます。
(2) GitHubにソースがコミットされたことをwebhookでJenkinsに通知する。
GitHubのwebhookという機能を使って、GitHubにコミットされたことをトリガーにして、Jenkinsの特定のURLを叩きます。webhookとは、あるサービスに対して外部から何らかの操作が行われたとき、そのことを他のサービスにHTTP経由で通知する仕組みです。この場合は、開発エンジニアがGitHubにソースコードをコミットしたことをJenkinsに知らせるためにwebhookの機能を使っております。webhookのURLは、通知される側(この場合はJenkins)によって指定されたものを使います。
(3) webhookでの通知を受けて、最新のソースコードをGitHubから取得する。
(2)でのwebhookでの通知を受けて、Jenkinsは最新のソースコードをGItHubからpullします。
(4) ビルド、ユニットテスト、Dockerイメージの作成を行う。
GitHubからpullしたソースコードをMavenでビルド、JUnitでテスト、さらにそのビルドしたイメージを含むDockerイメージを作成します。
(5) ACRにDockerイメージをpushする。
GitHubからACR(Azure Container Registry)に、(4)で作成したDockerイメージをpushします。Azure Container Registryは、Azure上で構築することができるDocker Hubのようなイメージです。Docker Hubのような、誰にでも公開するレジストリではなく、限られた人のみに公開するプライベートレジストリになります。Azureの各種サービスとも相性がよくございますので、是非ご利用をお薦め致します。
(6) ACRにDockerイメージがpushされたことをwebhookでWeb App for Containersに通知する。
このwebhookのしくみは、(2)でご説明したGitHubと同様です。
今回の実践では、アプリケーションを稼働させる基盤に「Web App for Containers」を採用しました。Web App for Containersは、以前からWebアプリケーションを稼働させるための基盤として実績のある「Azure Web Apps」をベースにしており、Web App for Containersが指定するDockerレジストリにDockerイメージをpushするだけで、アプリケーションを稼働することができます。Web Appsにもあった負荷分散、ステージングスロットを利用したBlue-Green Deploymentなどの機能は、Web App for Containersでも利用することができます。
ちなみに同様のサービスに、Azure Kubernetes Serviceがあり、こちらは一つのVMに複数のコンテナを配置することができますが、Web App for Containersに配置できるコンテナは一つのみです。ただ、Web App for Containersの場合、負荷分散、ステージングスロットなどの機能がマネージドサービスとして用意されているので、そのあたりの機能をご利用になりたい場合、Azure Kubernetes Serviceのようにyamlをゴリゴリ書く必要がございません。単一コンテナでの運用で十分なのであれば、Web App for Containersを是非ご検討下さい。
(7) ACRからのwebhookを受けて、Dockerイメージをpullする。
(6)でACRにDockerイメージのpushが完了されたことを通知するwebhookを受けて、Web App for ContainersはACRからDockerイメージをpullします。
(8) ACRからpullしたDockerイメージをもとに、コンテナを作成する。
ACRからpullしたDockerイメージをもとにコンテナを生成しますと、Webアプリケーションが稼働します。今回稼働させるWebアプリケーションは、画面に「Hello World!!」とだけ表示する非常にシンプルなものです。
以降では、このアプリケーションのことを「Hello Worldアプリケーション」と呼びます。
(9) SeleniumでUIテストを実施する。
Seleniumを使いUIテストを実施します。SeleniumはWebアプリケーションのテストを自動化してくれるツールで、今までマンパワーを使ってブラウザで行っていたテストは、全てSeleniumが代行してくれます。JavaやPythonなど多数の言語向けのライブラリも用意されており、簡単なコードでブラウザの動きをエミュレーションできます。
今回は、画面に表示されているのが「Hello World!!」かどうかを確認するテストをSeleniumで実施します。
以降、今回のテストを実施するSeleniumスクリプトを「UIテスト自動化スクリプト」と呼びます。
実際にやってみる
では、実際にやってみましょう(๑•̀ㅂ•́)و✧
Jenkinsのインストール
まずJenkinsをインストールします。みんな大好きJavaのインストールからです。
# yum install java-1.8.0-openjdk # yum install java-1.8.0-openjdk-devel
次にJenkinsのインストールです。
# wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins-ci.org/redhat-stable/jenkins.repo # rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key # yum install jenkins # systemctl enable jenkins # systemctl start jenkins
GitHubからソースコードをpullするので、gitのインストールが必要になります。
# yum install git
Seleniumを使うためにChrome Driverのインストールが必要になります。下記のURLにアクセスします。
https://chromedriver.chromium.org/downloads
2018年9月22日時点での画面になります。以下の「ChromeDriver 2.42」をクリックします。
「chromedriver_linux64.zip」をクリックして、ドライバーをダウンロードします。ZIPファイル解凍してできた「chromedriver」というファイルを/var/lib/jenkinsディレクトに置きます。
Seleniumを動作させるためにChromeが必要になりますので、インストールします。
# yum -y install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
ACRへのDockerイメージのpushにDockerが必要になりますので、インストールします。
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # yum makecache fast # yum install docker-ce
jenkinsユーザーでDockerを動かす必要があるので、dockerグループにjenkinsユーザーを追加します。そして、起動設定を行います。
# usermod -g docker jenkins # systemctl start docker # systemctl enable docker
次に、アプリケーションのビルドにMavenが必要になりますので、インストールします。これはJenkinsのGUIから行いますので、Jenkinsにアクセスします。URLは以下のとおりです。
https://[Jenkinsをインストールしたサーバーのホスト名]:8080/
以下の画面が表示されます。Jenkinsをインストールしたサーバーの/var/lib/jenkins/secrets/initialAdminPasswordのパスに記載のパスワードをテキストボックスに入力して、「Continue」をクリックします。
とりあえずJenkisnお薦めのプラグインを入れておきます。「Install suggested plugins」をクリックします。
しばらく待ちましょう。
ユーザ名やパスワードを入力して、「Save and Continue」をクリックします。
「Save and Finish」をクリックします。
「Start using Jenkins」をクリックします。
「Jenkinsの管理」をクリックします。
「Global Tool Configuration」をクリックします。
「Maven追加」をクリックします。「名前」のところに「M3」と入力して、「Save」をクリックします。
Jenkinsのインストールと設定はこれで終わりです。
Azure Container Registryの設定
Azure Container Registryを設定します。Azureポータルにアクセスします。「リソースの作成」をクリックして、虫眼鏡が書いてあるテキストボックスに「container」と記入して、Enterをクリックします。「Container Registry」をクリックします。
「作成」をクリックします。
レジストリ名は任意のものを、サブスクリプション、リソースグループ、場所は環境に応じたもの、管理者ユーザーは「有効にする」、その他はデフォルトのままにして、「作成」をクリックして下さい。
Hello WorldアプリケーションのDockerイメージ作成
先程ご紹介した「Hello World!!」を画面に表示するプリケーションのDockerイメージを作成します。以下のGitHubにあるソースコードをCloneして下さい。
https://github.com/noriyukitakei/spring-boot-hello-world
これは、JavaのアプリケーションフレームワークであるSpring Bootで作成されたものです。画面に「Hello World!!」と表示するだけの単純なアプリケーションです。アプリケーション自体のソースコードの説明は省きます。
Cloneしたソースコードのトップディレクトリに移動して、以下のコマンドでアプリケーションをビルドします。
# mvn clean package
本ブログでは、CI/CDの説明がメインなので、アプリケーションのソースコードやビルドについてのご説明は割愛させて頂きます。先のビルドコマンドもここでは、ご理解頂くなくても大丈夫です。
次にDockerfileによるビルドを行いますが、その前にDockerfileの中身を見てみます。先程CloneしたソースコードのトップディレクトリにDockerfileがあります。
FROM tomcat:8.5.33-jre10 COPY target/helloworld.war /usr/local/tomcat/webapps/helloworld.war
たった2行なのですが^^;1行目は、Docker HubからTomcatが稼働するイメージを取得してきています。2行目では、「mvn clean package」のコマンドでビルドしたアプリケーションをDockerイメージの/usr/local/tomcat/webappsディレクトリにコピーしています。これだけで、Tomcat上で稼働するWebアプリケーションのイメージが出来上がります。
では、Dockerビルドしましょう。
docker build -t helloworld .
きちんとイメージが出来上がっているかどうか確かめてみましょう。
i$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE helloworld latest XXXXXXXXXXXX 8 minutes ago 685MB
おおー(๑•̀ㅂ•́)و✧
では、これをAzure Container Registryにpushしてみましょう。
ここから先の作業は、Azure CLIが必要なので、以下のURLに従って、インストールして下さい。
https://docs.microsoft.com/ja-jp/cli/azure/install-azure-cli
Azure CLIでAzureにログインします。
$ az login To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code XXXXXXXXX to authenticate.
上記のメッセージに表示されているURL「https://microsoft.com/devicelogin」にアクセスして、「enter the code XXXXXXXXX to authenticate.」のXXXXXXXXXを入力しまと「続行」というボタンが表示されますのでクリックします。
しばらくすると、「az login」と入力したコンソールの方に、ずらずらーっとJSONが表示されたらログイン成功です。
次に、先程作成したAzure Container Registryにログインします。「–name」のオプションには、Azure Container Registryを作成した時に指定した「レジストリ名」を入力します。Login Succeededが表示されれば成功です。
$ az acr login --name devops2 Login Succeeded
Azure Container Registryのホスト名は、「レジストリ名.azurecr.io」となりますので、以下のようにpushします。
$ docker tag helloworld devops2.azurecr.io/helloworld $ docker push devops2.azurecr.io/helloworld
これで、Dockerイメージのアップロードは完了です。
Hello WorldアプリケーションのソースコードのGitHubへのpush
先程CloneしたソースコードをGitHubにリポジトリを作成して、そのリポジトリにpushして下さい。
※本ブログではGitHubの詳細な操作は割愛させて頂いております
Web App for Containersの設定
Web App for Containersを設定します。Azureポータルにアクセスします。「リソースの作成」をクリックして、虫眼鏡が書いてあるテキストボックスに「web app」と記入して、Enterをクリックします。表示されるリストの中から「Web App」をクリックします。
「作成」をクリックします。
「アプリ名」は任意のもの、「サブスクリプション」「リソースグループ」は環境に応じたもの、「OS」は「Docker」を選択して下さい。「コンテナーの構成」をクリックして下さい。
「イメージのソース」に「Azure Container Registry」を選択、レジストリ名にはAzure Container Registry作成時に指定したレジストリ名、「helloworld」、タグには「latest」(こちらは先程Dockerイメージを作成したときの情報です)を選択して、「OK」をクリックします。
最後に「作成」をクリックして下さい。
以下のURLにアクセスすると、ブラウザに「Hello World!!」と表示されるはずです。
https://[先程入力したアプリ名].azurewebsites.net/helloworld/hello
SeleniumによるUIテスト自動化スクリプトの作成
Seleniumで自動化するためのスクリプトを用意します。
以下のGitHubに今回必要なSeleniumのスクリプトを用意しましたので、Cloneして下さい。
https://github.com/noriyukitakei/spring-boot-hello-world-e2e
今回、SeleniumのテストスクリプトはMavenプロジェクトにおけるJUnitのテストケースとして作成します。そのテストスクリプトはsrc/test/java/com/sios/test/E2ETest.javaに鬼窟されており、その詳細は以下の通りになります。
そして、GitHubにリポジトリを作成して、そのリポジトリにUIテスト自動化スクリプトのソースコードをpushして下さい。
※本ブログではGitHubの詳細な操作は割愛させて頂いております
パイプラインによる自動化スクリプトの作成
Jenkinsにはパイプラインという機能があり、自動化のスクリプトを作成することができます。今回はこれを使ってCI/CDを実現します。
その前にまず、自動化スクリプトを作成するために必要な情報をAzureポータルから取得します。Azure Container Registryを作成したリソースグループに移動して、表示されるリソースのリストから、種類が「コンテナーレジストリ」のリソースをクリックします。
「アクセスキー」をクリックして表示される「ログインサーバー」「ユーザー名」「password」をメモっておいて下さい。
Jenkinsの画面に戻って、「新規ジョブ作成」をクリックします。
「Enter an item name」というテキストボックスに任意のジョブ名(ここではhelloworld)と入力して、「パイプライン」を選択して「OK」をクリックします。
しばらくスクロールすると、「パイプライン」という項目が見えてきます。
上図のScriptの部分に以下のスクリプトを入力して、「保存」をクリックします。
Jenkinsによるメール通知の設定
パイプラインスクリプトにて、JenkinsによるCI/CDが失敗したらメールで通知する処理を記述しましたが、そもそもシステム設定にて、メールを送信できるようにしなければ、正常にメールは送信されません。
「Jenkinsの管理」→「システムの設定」の順にクリックします。
「システム管理者のメールアドレス」に通知メールの送信元アドレスを入力します。
「E-mail通知」の項目に、メールを送信するために必要な情報を入力します。こちらは環境に応じて適切な設定を行って下さい。最後に「保存」をクリックします。
GitHubのwebhookの設定
GitHubにソースがコミットされたことをJenkinsに通知するためのwebhookの設定を行います。
Jenkinsのトップ画面から、先程作成したジョブをクリックします。
「設定」をクリックします。
「ビルドトリガ」までスクロールして、「リモートからビルド」をチェックします。「認証トークン」の部分に任意の文字列を入力します。これはGitHubがJenkinsに対してwebhookする際の認証キーになりますので、「hoge」とか安易なものを指定しないで下さい。認証トークンは後ほど使いますので、メモっておいて下さい。最後に「保存」をクリックします。
次に、webhookの設定に必要なAPIトークンを取得します。Jenkinsのトップ画面に戻って、「Jenkinsの管理」をクリックします。
「ユーザーの管理」をクリックします。
適当なユーザー名をクリックします。
「設定」をクリックすると、画面右部に「APIトークン」が表示されます。「Add new Token」をクリックします。
「Generate」をクリックします。
APIトークンが生成され表示されます。このAPIトークンと、このトークンを割当てられたユーザー名をメモしておいて下さい。
Hello WorldアプリケーションをpushしたGitHubにアクセスします。「Settings」→「Webhooks」の順にクリックします。
「Add webhook」をクリックします。
「Payload URL」に以下のURLを設定して下さい。それ以外は、下図の画面の通りでOKです。最後に「Add webhook」をクリックします。
https://[Jenkinsのユーザー名]:[APIトークン]@[Jenkinsのホスト名]:8080/job/[Jenkinsのジョブ名]/build?token=[認証トークン]
これでGitHubへのwebhookの設定は完了です。
Azure Container Registryのwebhookの設定
Azure Container RegistryにDockerイメージがpushされたときに、Web Apps for ContainersがそのDockerイメージを取得してコンテナを自動で生成するためのwebhookを作成します。
まず、AzureポータルからWeb App for Containersのリソースにアクセスします。「コンテナーの設定」をクリックして、「継続的なデプロイ」を「オン」にして、「保存」をクリックします。
マイクロソフトのドキュメントを見ると、本当はこれだけでAzure Container Registryにwebhookが追加されるはずなのですが、なぜか追加されませんでした(´・ω・`)
しょうがないので、Azure Container Registryに手動でwebhookを追加することにしました(´・ω・`)
先程の「コンテナーの設定」をもう一度だけクリックします。「イメージのソース」のところで「Docker Hub」をクリックします。
下の方にスクロールすると「継続的なデプロイ」が見えてきます。「URLの表示」をクリックして表示されるURLをコピーします。
AzureポータルからAzure Container Registryのリソースにアクセスします。「Webhooks」をクリックします。画面右部に表示される「追加」をクリックします。
webhook名は任意の名称、「サービスURI」は先程、Web App for Containersの「継続的なデプロイ」の設定でコピーした「WEBHOOKのURL」を入力、後の項目は下図のままで、最後に「作成」をクリックします。
試しにやってみよう!!
さぁ、これで準備は整いました(๑•̀ㅂ•́)و✧
Hello Worldアプリケーションのソースコードに適当なコメント文を入れて、GitHubにpushしてみませう。
Jenkinsのジョブの画面を見てみると、何やら始まったと思います。
アプリケーションのビルドが終わって、Dockerイメージのpushが始まりました(๑•̀ㅂ•́)و✧
UIテストが始まりました。もうちょっと・・・(;´Д`)
終わったーヽ(=´▽`=)ノ 大成功です(๑•̀ㅂ•́)و✧
最後に
2回シリーズで「コンテナ時代のDevOps」という題材にして連載致しましたが、いかがでしょうか?なんとも抽象的なDevOpsというもののイメージを掴んで頂き、実践で投入頂く一助になれば、誠に幸いにございます。では、No CI/CD、No Lifeということで、楽しいDevOpsライフを楽しんで頂ければと思います。