ASP.NET Core MVCでブログを作ってCI構築してそこからデプロイするようにした

 .NET Core 2.0が出たので、このブログのエンジンを再構築しなおした。ついでにDockerコンテナで運用するようにし、ホスティングもコンテナでやるHyper.shに移る。
デプロイは、
開発→Github→AzureWebApp
だったのが、
開発→Github→TravisCI→Hyper.sh
になり、自動テストを経ることになった。masterへのコミットのみ、Hyper.shへのデプロイが実行されるようにしてある。あとはCIでOAuthつけたらひと段落。
https://github.com/hMatoba/tetsujin


https://blog.hmatoba.net
comment: 0

TravisCIからHyper.shへDockerコンテナなアプリを継続的デプロイ

 Dockerコンテナなアプリをホビー用途でデプロイするならHyper.shがとてもイカしてる。そんなHyper.shとTravisCIを掛け合わせて継続的デプロイを組んでみる。

 このブログで、TravisCIから、テストにとおったアプリのDockerイメージを、継続的にDocker hubへプッシュしていくまではやっている。
.NET CoreのDockerコンテナに入ったWebアプリをTravisCIでCI
 今回はDocker hubへのプッシュ後に、Hyper.shのCLIツールをそのままTravisCIで使ってDockerコンテナを走らせるまで。

 まずHyper.shでアクセストークンとキートークンを発行し、TravisCIで環境変数にセット。




 続いて.travis.ymlにHyper.shのCLIツールでの処理(コンテナ立ち上げ)を追加。
.travis.yml

after_success:
- docker tag matoba/dncindocker:ci matoba/dncindocker:latest
- docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
- docker push matoba/dncindocker:latest
- wget https://hyper-install.s3.amazonaws.com/hyper-linux-x86_64.tar.gz
- tar xzf hyper-linux-x86_64.tar.gz
- ./hyper --help
- ./hyper config --accesskey ${HYPER_ACCESS} --secretkey ${HYPER_KEY}
- ./hyper run -d -p 80:80 --name mersault matoba/dncindocker:latest



 上記までで設定はOK。TravisCIでのテストを走らせる前、Hyper.shではコンテナやイメージはまだゼロ。



 TravisCIでのテストが通ったあとに見るとコンテナやイメージにカウントが増えている



 しっかりコンテナが動いている。



 IPを当ててブラウザでアクセスしてみる。



 管理コンソールを見ていると環境変数を入れるフォームはなさそう。そうなると環境変数を与えられるタイミングはコンテナを起動させるタイミングである。アプリで使われる環境変数はTravisCIに入れて運用していくことになるんかな。
comment: 0

Azure Web App on LinuxでDockerコンテナによるデプロイをしてみる

 前回でTravisCIからDocker hubへ、テストにとおったDockerイメージをプッシュした。これのデプロイ先としてAzure Web App on Linuxを選んだ場合をちょっとやってみる。

 AzureポータルでWeb App on Linuxを選び、イメージのソースをDocker hubに上げてあるイメージを指定。そして進む。


 デプロイが済むまでちょい待ってからアクセスしてみると、しっかりアプリが起動している。あれ?デプロイこんだけで済んじゃう?という感想。



 ところで、遊びに使うにはちょい高い。まあアプリケーションに注力するために、OSなどをよしなにやってくれるマネージドだからこんなところか。



 Docker hubとAzureの連携で継続的デプロイも可能。
Azure Web App on Linux での Docker Hub の継続的なデプロイ





comment: 0

.NET CoreのDockerコンテナに入ったWebアプリをTravisCIでCI

 VisualStudioで作成された.dcprojをdotnetコマンドでビルドしようとすると、"Microsoft.Docker.Sdkのほにゃららがない"と言われる。
The imported project "C:\Program Files\dotnet\sdk\1.0.0\Sdks\Microsoft.Docker.Sdk\Sdk\Sdk.props" was not found.


これを言われるのはWindows環境でもLinux環境でも。dotnet cliでイシューとして挙げられている。
VS2017 Docker-Compose Project breaks build on command line
必要なSDKはdotnet cliのディレクトリにはないが、VisualStudioのディレクトリには入っている。これを使えばまあできんこともないが、一時的な策になってしまう。

 dotnetコマンドで.dcprojをビルドするのはここではあきらめる。
 そもそもぼくはなにがしたいのか。VisualStudioで作ったdocker-compose入りのプロジェクトをビルドしたかった。TravisCI上でdotnetコマンドでプロジェクトをビルドして、そこから出てきたDockerイメージをDocker hubへプッシュしたかった。

 まあそもそも.dcprojのビルドは、dotnetコマンドでは無理だがVisualStudioを使えばビルドできる。それを踏まえて。
代替案
・必要なファイルを開発環境のWindowsで用意してTravisCIへ送って、DockerイメージをTravisCIでビルドしてテストがうまくいったら、Docker hubへプッシュ
・開発環境でVisualStudioでビルドしたDockerイメージをTravisCIでプルしてテスト。テストに通ったらDockerイメージをリネームしてプッシュ

 一つ目。デフォで必要なビルドしてファイルがgitでignoreされているので、ここのデフォ設定をいじらなければならない。その結果、変更を追いかけるファイルが増えてアレ
 二つ目。手っ取り早い。これでいいや。まあ暫定なので、.dcprojがビルドできないバグが直ったら改めて考える。


 一通りやってみたGithubリポジトリ↓
https://github.com/hMatoba/DNCinDocker
ロクに参考資料がないのをトライアンドエラーでやったので、コミットタイトルは超適当。

 .NET CoreのWebアプリが作成できたらリリース設定でプロジェクトをビルドし、WebアプリのDockerイメージを得る。Dockerイメージには"ci"というタグをつけておくことにする。そのイメージをDocker hubへプッシュしておく。

 Docker hubにプッシュしてあるイメージを使ったTravisCIでのテストを用意する。TestWithSeleniumというプロジェクトでSeleniumを使ったテストを用意した。これをdocker-composeで管理する。TravisCI上で使うためのdocker-composeファイルを用意する。
docker-compose.travis.yml

version: '2'

services:
dncindocker:
image: matoba/dncindocker:ci
ports:
- "8080:80"
selenium:
image: selenium/standalone-chrome
ports:
- "4444:4444"
links:
- dncindocker:webapp

 上記を使ってTravisCI上でテストを走らせる。
language: csharp

mono: none
dotnet: 1.0.4
dist: trusty
services:
- docker

env:
- DOCKER_COMPOSE_VERSION=1.8.0

before_install:
- sudo rm /usr/local/bin/docker-compose
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
- docker-compose -f docker-compose.travis.yml config
- docker-compose -f docker-compose.travis.yml build
- docker-compose -f docker-compose.travis.yml up -d
- sudo pip install selenium

script:
- cd ./TestWithSelenium
- python setup.py test

after_success:
- docker tag matoba/dncindocker:ci matoba/dncindocker:latest
- docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}"
- docker push matoba/dncindocker:latest
matrix:
fast_finish: true

 成功後にDockerイメージをリネームしてプッシュするので、Docker hubのIDとパスワードを使わなければならない。これは環境変数で埋め込む。

 一通りファイルがそろったのでGithubへプッシュしてみる。そのままTravisCIへ流れるように設定してある。







TravisCIでテストはとおっている様子。




Docker hubに、開発環境からプッシュされたciタグのイメージと、TravisCIからプッシュされたlatestタグのイメージが上がっている。

 ちなみにTravisCIで行っているコードの中身としては、必要なもののインストールとテストだけである。必要なものはdocker-composeとPythonのSeleniumドライバだけ。あとのテストコードはdocker-composeとPythonで処理される。つまり、このテストはWindowsでも実行できる。開発環境でもテストを検証できるってこと。便利。
comment: 0

TravisCIでDockerに入ったWebアプリのSeleniumテスト

 WebアプリをDockerでビルドして、そこでできたイメージをデプロイしてコンテナを走らせるってケースは増えてきているはず。そのイメージを使ってTravisCI上でSeleniumを使ってテストしてみる。


 Dockerイメージは既にDocker Hubにアップしてあるものとする。今回使うのは、Webアプリで、リクエストを送ると世界へのあいさつを返すだけのごく初歩的なものだ。テストはSeleniumを使ってリクエストを送り、レスポンスのHTMLのタイトルをチェックするものとする。

 テストに使うSeleniumを用意する。Seleniumはホスト環境に用意するのもいいが、仮想ディスプレイを使ったりすると、自分の環境でTravisCIでやるコマンドをちょっと試したかったりする場合に用意が手間になる。SeleniumもDockerで公式のものが用意されているので、今回はDockerで用意されたものを使う。

 Seleniumを動かすテストコードは、今回はPythonを使う。
 DockerコンテナとしてWebアプリとSeleniumが動いており、ホストにSeleniumを動かすPythonがあるというのが今回の環境。コンテナが二つあるので、ここらはdocker-composeを使うことにする。

 まずWebアプリとSeleniumのある環境の準備のためにdocker-compose。docker-compose.ymlを用意する。
docker-compose.yml

version: '2'

services:
tornadoapp:
image: matoba/tornadoapp
ports:
- "80:80"
selenium:
image: selenium/standalone-chrome
ports:
- "4444:4444"
links:
- tornadoapp

 WebアプリはTornadoを使って作ったのでtornadoappという名前にしてある。ポートバインドで、ホストのポート80でこのWebアプリがlistenされることになっている。
 あとSeleniumは、Pythonドライバで接続するためにポート4444でlistenしているのと、Webアプリに名前でアクセスができるようにlinksで設定してある。
 環境はこれでOK。

 ホストで動く、Seleniumを動かすPythonを用意する。"python setup.py test"のコマンドで動かすので、setup.pyと実際のテストコードを用意する。./TestWithSelenium以下にsetup.pyと、tests/s_test.pyが必要。
setup.py

from setuptools import setup
import sys

sys.path.append('./tests')

setup(
name='browsertest',
version='1.0',
description='test a project on browser',
test_suite = 's_test.suite',
install_requires=[
'selenium',
],
)


s_test.py

import unittest

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

#HOST = "http://172.17.0.1"
HOST = "http://tornadoapp"

class BrowserTests(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Remote(
command_executor = 'http://127.0.0.1:4444/wd/hub',
desired_capabilities = DesiredCapabilities.CHROME
)
self.driver.implicitly_wait(10)

def test_top(self):
"""top page"""
self.driver.get(HOST + "/")
self.assertIn("foo", self.driver.title)

def suite():
"""run tests"""
suite = unittest.TestSuite()
suite.addTests([unittest.makeSuite(BrowserTests)])
return suite


if __name__ == '__main__':
unittest.main()

 SeleniumからWebアプリへのアクセスはdocker-composeで設定した名前で行っている。その他の手段としては、ポートがホストにバインドされていれば、IPでアクセスできる。Dockerネットワークのデフォルトは172.17.0.*なのでこれを使っていいはず。

 テストが用意できたら、あとはこれをTravisCIで動かすための設定ファイルを用意する。
.travis.yml

sudo: required

language: python

python:
- 3.6

services:
- docker

env:
- DOCKER_COMPOSE_VERSION=1.8.0

before_install:
- sudo rm /usr/local/bin/docker-compose
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
- docker-compose build
- docker-compose up -d
- pip install selenium

script:
- cd ./TestWithSelenium
- python setup.py test

matrix:
fast_finish: true

 やっていること↓
前準備
・Dockerを使えるように
・docker-composeコマンドを使えるように
・WebアプリコンテナとSeleniumコンテナを用意
・PythonのSeleniumドライバを用意
テスト
・Pythonコードを走らせる

 これでTravisCIでコンテナに入ったWebアプリを、Seleniumでテストする準備ができた。あとはアップするだけ。設定などを間違えていなければこれでテストは通る。




今回のTravisCI
https://travis-ci.org/hMatoba/PlayDockerTest
comment: 0