しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

AppVeyor を使って ASP.NET MVC アプリケーションの Docker Image を自動で作成してみる

前に AppVeyor の Windows Server 2016 と Docker 対応について調べたので、今回は実際に ASP.NET MVC アプリケーションをビルドして、Docker Image の作成までを行ってみます。

やることは CircleCI と Docker を使って App Service on Linux への CI/CD を試した時とほぼ変わりません。処理をそのまま AppVeyor と ASP.NET 向けに修正した形です。

Windows Server Core のイメージが 10GB ぐらいあるので、ビルドにも時間がかかって使い物にならないかもと思いましたが、今回の場合 2 分以下で終わりました。実用的な気がしてきます。

最初に ASP.NET MVC アプリケーションを作成してから、appveyor.yml を書いていきます。

appveyor.yml を用意する

とりあえず作成した appveyor.yml を全て載せておきます。build / test / deploy のそれぞれでカスタムなスクリプトを書いていますが、やっていること自体は大したことはありません。

テストでは作成したイメージを起動して、ちゃんとレスポンスを返すか確認しています。*1

version: '{build}'

image: Visual Studio 2017

environment:
  DOCKER_USER: XXXXXXX
  DOCKER_PASS:
    secure: XXXXXXX

before_build:
  - nuget restore

build_script:
  - msbuild .\AspNetApplication\AspNetApplication.csproj /nologo /verbosity:m /t:Build /t:pipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="..\publish";AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release
  - docker build -t shibayan/appveyor-aspnet-docker .

test_script:
  - ps: |
      $cid = docker run -d shibayan/appveyor-aspnet-docker
      $hostip = docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" $cid
      curl "http://${hostip}" -UseBasicParsing

deploy_script:
  - docker login -u %DOCKER_USER% -p %DOCKER_PASS%
  - docker push shibayan/appveyor-aspnet-docker

面倒なのが IP を inspect で取得する部分です。これはしばらく改善しなさそうなので諦め気味です。

用意した Dockerfile は以前に試したものとほぼ変わらず、wwwroot 以下にビルドした成果物をコピーするだけの簡単なものです。ベースイメージは 4.6.2 とタグを固定しました。

FROM microsoft/aspnet:4.6.2

COPY ./publish/ /inetpub/wwwroot

MSBuild によってビルドされたファイルは publish というディレクトリに全て保存されるので、その中身をそっくり wwwroot にコピーしています。

イメージのテストが通れば、後は Docker Hub に push するだけという簡単な処理です。

AppVeyor で実際にビルド

GitHub にリポジトリを作成して、AppVeyor で実際にビルドしてみました。事前に調べていた甲斐もあって、特に失敗することなく Docker Hub への push まで上手くいきました。

MSBuild 周りが一番複雑な部分ですが、App Service で良く使っていたコマンドなので問題なかったです。

f:id:shiba-yan:20170502184818p:plain

MSBuild が終わると Docker Image を作成します。microsoft/aspnet の pull に 1 分ぐらいかかるので、予め pull しておきたい気持ちでいっぱいです。

Docker Image の作成が終わると、実際に起動してテストを行っています。

f:id:shiba-yan:20170502184851p:plain

今回のコマンドでは Razor 周りのプリコンパイルまでは行っていないので、起動するまでに少し時間がかかりますが、それでも数秒で成功します。

最後に Docker Hub に push して完了ですが、例によって Azure Container Registry などに push する形にしても良いかと思います。特に ACS を使う場合には便利だと思います。

作成したイメージの動作確認

AppVeyor でのビルドが成功すると Docker Hub に作成されたイメージが追加されているので、検証用の Windows Server 2016 が入ったサーバーを使って動作確認をしておきます。

テストで利用しているコマンドとほぼ同じものを実行すると、Docker Hub から pull してくれます。

f:id:shiba-yan:20170502182213p:plain

一応 PowerShell 上でも同じように URL を叩いてレスポンスが返ってくるのを確認しました。

コンテナホストからは確認できたので、外部の PC からブラウザを使って確認してみました。外部からのアクセス時には WinNAT によってポート変換がされるので 8080 が必要です。

f:id:shiba-yan:20170502182915p:plain

すんなりと ASP.NET MVC アプリケーションが動作しました。コンテナとホストでビルド番号を合わせる必要があるという手間はかかってきますが、手軽にアプリケーションを実行できるのは魅力です。

Azure Container Service や EC2 Container Service などの Windows Server Containers に対応した環境にそのまま持っていけるはずですが、まだ正式リリースされていないのが課題という感じです。

*1:個人的にはちゃんと動かないイメージを生焼けと呼んでます。どうでもいい話だった。