しばやん雑記

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

Windows Server Insider Preview を使って Server Core と Nano Server の Insider Image を試す

あまり Windows Server Insider Preview に関しては興味がなかったのですが、たまたま見つけた Insider 版の Windows Server Core と Nano Server の Docker Image がかなり最適化されていたので、実際に試してみたくなりました。地味にはまりましたが何とか動いたという苦労話です。

手持ちの Hyper-V を入れてある Windows Server 2016 に Insider Preview を入れました。

ダウンロードには Insider Preview への参加が必要ですが、Windows 10 で参加しておけば OK です。

Server Core 版のみ提供されているので、インストールイメージは 2GB ちょいなので小さめですね。

Download Windows Server Insider Preview

最初は Azure 上に作ろうかと思いましたが、ぶちぞう RD から難しそうと言われたので止めました。将来的には Azure で Insider Preview のイメージが提供される気がします。

Windows Server Insider Preview を用意

とりあえず Hyper-V を使って、サクッと Insider Preview をインストールします。コンテナを実行するのでメモリだけは少し多めに確保した方が良い気がしました。

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

Server Core の初期セットアップ初めてでしたが、基本はパスワード入れるだけです。

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

Insideer Preview 自体はすぐに入るのですが、その後の Docker インストールで大きく躓きました。すぐに直る気がしますが、ひとまずは回避法を次で紹介しておきます。

Docker をインストール

Docs に Insider Container を使う方法が書いてあるので、基本はこの通りにコマンドを打ち込めばよいはずなのですが、何故か上手くいきませんでした。

Using Insider Container Images | Microsoft Docs

Docker をダウンロードした後のハッシュチェックが通りませんでした。

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

Provider のコードを読むと、既にファイルがある場合にはダウンロードをスキップするようになっていたので、事前にダウンロードしておきました。パスはユーザーによって異なると思います。

Invoke-WebRequest https://dockermsft.blob.core.windows.net/dockercontainer/docker-17-06-0-ce.zip 
    -OutFile C:\Users\ADMINI~1\AppData\Local\Temp\1\DockerMsftProviderInsider\Docker-17-06-0-ce.zip

この後に再度インストールを実行すると上手くいきました。本当に謎です。

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

再起動すると dockerd が立ち上がるので、実際にコマンドが使えるようになります。エラーでサービスが立ち上がらなかった時には、もう一度再起動すると上手くいくこともあるみたいです。

Insider Image を試してみる

Docker のインストールに非常に手間と時間をかけてしまいましたが、これでようやく Insider Preview な Image を試すことが出来ます。公開されているベースイメージは以下の通り。

https://hub.docker.com/r/microsoft/windowsservercore-insider/
https://hub.docker.com/r/microsoft/nanoserver-insider/

他にも .NET Core 2.0 や PowerShell が入っているものはあります。

大きな特徴として、イメージサイズが両方とも半分以下になっています。てっきりコンテナに最適化されるのは Nano Server だけかと思ってましたが、Server Core も最適化されました。

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

これまでの Windows Server Core と Nano Server のサイズは以下の通りです。

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

展開後のサイズで Nano Server が 200MB を切っているのは割と頑張ったほうだと思います。Server Core はまだまだ大きいですが、それでも .NET Framework の実行環境として扱いやすくなりました。

当然ながら Windows Server Containers ですんなりと動作します。

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

起動時間の短縮とかはなさそうですが、サイズが小さくなったのは非常に嬉しいです。

Server Core Insider に IIS を入れる

Windows Containers を使ってやりたいことは ASP.NET アプリケーションの Dockernize なので、最低でも IIS を入れて動かしておくことにします。

IIS や ASP.NET の Dockerfile は GitHub に公開されてるので、FROM を買えるだけで使えます。

GitHub からリポジトリを落としてきて、Dockerfile を以下のように書き換えてビルドすると IIS がインストールされた Server Core Insider の Docker Image が完成します。

FROM microsoft/windowsservercore-insider

RUN powershell -Command Add-WindowsFeature Web-Server

ADD ServiceMonitor.exe /ServiceMonitor.exe

EXPOSE 80

ENTRYPOINT ["C:\\ServiceMonitor.exe", "w3svc"]

Dockerfile だけではなく ServiceMonitor が必要なので少し注意が必要です。

ビルドしたイメージを起動すると、当たり前ですが IIS にアクセスできるようになります。特筆すべきことはありませんでしたが、当たり前に動作するというのは重要なポイントかなと。

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

Windows Containers を運用する上で大変なのは Docker Image のサイズとコンテナホストとのバージョンミスマッチの二つだったので、次のリリースでイメージのサイズに関しては解消されそうです。

コンテナホストとのバージョンミスマッチに関しては Hyper-V Containers が使える Dv3 / Ev3 で半分は解消されたと思ってます。後は Kubernetes 側で isolation を選べるようになれば良いですね。

Docker for Windows Server 2016 のアップデートを行う方法

Windows Server 2016 への Docker インストールは、PowerShell を使って結構簡単に出来るのですが、アップデート方法をこれまであまり見たことがありませんでした。

何回か書いた気はしますが、インストールは以下のコマンドを実行するだけです。

Install-Module -Name DockerMsftProvider -Force
Install-Package -Name docker -ProviderName DockerMsftProvider -Force
Restart-Computer -Force

自宅にある検証マシンに入っている Docker は 1.13 と古いものだったので、簡単にアップデートする方法がないか少し探してみると、PowerShell を使って簡単にアップデート出来るようでした。

ドキュメントの分かりにくい部分にアップデート方法が書いてありました。

Tip: If you want to update Docker later:

  • Check the installed version with Get-Package -Name Docker -ProviderName DockerMsftProvider
  • Find the current version with Find-Package -Name Docker -ProviderName DockerMsftProvider
  • When you're ready, upgrade with Install-Package -Name Docker -ProviderName DockerMsftProvider -Update -Force, followed by Start-Service Docker
Windows Containers on Windows Server | Microsoft Docs

実質、実行するコマンドは以下の 1 行だけです。インストールの時と異なり、Update スイッチが追加になっているだけです。コマンドレット名が分かりにくいですが、これでアップデートも行えるみたいです。

Install-Package -Name docker -ProviderName DockerMsftProvider -Verbose -Update

実際に自宅の検証マシンに対して Docker のアップデートを行ってみました。

Docker 1.13 へのアップデートは半分手動で行った記憶がありますが、関係なく PowerShell でアップデートが出来るようです。これはかなり簡単でした。

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

アップデートが完了した後は dockerd が立ち上がっていなかったですが、Windows Update のついでに再起動を行ってみると無事に立ち上がってきました。

docker version を実行してみると、ちゃんと最新の 17.03.1-ee-3 になっていることが確認できますね。

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

Windows Server 2016 では追加コスト無しで EE 版が使えるようになってるので、自然とこのバージョンが落ちてくるようです。手順をすぐに忘れそうなので、メモ代わりに残しておきます。

Kubernetes で .NET アプリケーションな Job を動かしてみる

Kubernetes には Job という機能があることを知ったので、Windows Server Containers でも試してみました。使いどころはわかってないですが、Windows でも動くことを確認したかったのです。

動き続けるタイプの Job を作りたい場合には、これまで通り Deployment と Replica Set を使った方が良さそうです。Job のイメージ定義は immutable なので後から変更できません。

とりあえず適当にコンソールアプリケーションを作成します。標準出力にメッセージを書くだけのアプリケーションをサクッと用意してビルドします。

using System;
using System.Threading;

namespace JobApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello Job : " + DateTime.Now);
        }
    }
}

このアプリケーションをイメージ化するために用意した Dockerfile は以下の通りです。ENTRYPOINT としてビルドしたアプリケーションを指定して、実行が終わったらコンテナも終わるようにします。

FROM では .NET Framework 4.6.2 のイメージを明示的に指定しておきます。ちなみに microsoft/dotnet は .NET Core を使うイメージなので注意。

FROM microsoft/dotnet-framework:4.6.2

COPY app /app

WORKDIR /app

ENTRYPOINT ["JobApplication.exe"]

作成したイメージを Docker Hub に push し、Kubernetes にデプロイするための YAML を用意します。ダッシュボードから作れないので YAML を用意する必要がありました。

最重要ポイントとして nodeSelector で os を windows として明示的に指定しないと、Linux で動作しているマスターにデプロイされて詰みます。

apiVersion: batch/v1
kind: Job
metadata:
  name: dotnet-job
spec:
  template:
    metadata:
      name: dotnet-job
    spec:
      containers:
      - name: dotnet-job
        image: shibayan/dotnet-job
      restartPolicy: OnFailure
      nodeSelector:
        beta.kubernetes.io/os: windows

これに気が付かずに何回も pull 時にエラーを出してしまって悩みました。デプロイメントを作成した時に上手くいった理由はよくわからないですが、Windows Server Containers を使うので指定は必要だと思います。

YAML を作成したら Kubernetes のダッシュボードからアップロードするだけです。

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

デプロイが完了すると Job が実行されて、ログが見れるようになります。

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

とりあえず Windows Server Containers でも動作はしましたが、再実行するには Job の再デプロイが必要なので、いまいち使いどころがやっぱりわかりませんでした。

ちょっと前に追加された Cron Jobs の方が使いどころが多いと思いました。

しかし、現在の Azure Container Service で作られた Kubernetes では有効化されていないので、残念ながらデプロイのタイミングで検証エラーになってしまいます。

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

acs-engine を使えばカスタマイズ出来そうですが、それはまた今度試してみることにします。

nodeSelector について学べたので、今回はそれで良しとしておきます。

AppVeyor から Azure Container Service 上の Kubernetes へ自動でデプロイを行う

これまで AppVeyor と Kubernetes でやってきたことの集大成として、AppVeyor から Azure Container Service 上の Kubernetes への自動デプロイを試してみます。

やってきたことは以下のエントリを参照してください。Kubernetes はかなり良いですね。

AppVeyor から Kubernetes にデプロイするためには、認証情報が必要なので先に作成しておきます。

Service Account Token を取得

トークンを作成するためには kubectl を使って Service Account をまず作成する必要があります。

kubectl create serviceaccount appveyor

コマンドで Service Account を作成したら、ダッシュボードでトークンを確認できるので簡単です。

コンフィグの中にあるシークレットから、Base64 デコード済みのトークンをコピーできます。

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

作成はコマンドで作りますが、削除と編集はダッシュボードから簡単に行えるのがアンバランスでした。

appveyor.yml に処理を追加

現在の Kubernetes ダッシュボードは以下のようになっています。基本的にアップデートを行うだけなので、予めアプリケーションはデプロイしてあります。

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

appveyor.yml には kubectl のダウンロードと、イメージの更新コマンドを追加します。

version: '{build}'

image: Visual Studio 2017

environment:
  DOCKER_USER: XXXXX
  DOCKER_PASS:
    secure: XXXXX
  DOCKER_IMAGE_NAME: shibayan/appveyor-aspnet-docker:$(APPVEYOR_REPO_BRANCH)-$(APPVEYOR_BUILD_NUMBER)
  KUBE_MASTER: https://XXXXX
  KUBE_TOKEN:
    secure: XXXXX

install:
  - curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.6.2/bin/windows/amd64/kubectl.exe

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 %DOCKER_IMAGE_NAME% .

test_script:
  - ps: |
      $cid = docker run -d $env:DOCKER_IMAGE_NAME
      $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 %DOCKER_IMAGE_NAME%
  - kubectl set image deployment/aspnet aspnet=%DOCKER_IMAGE_NAME% --server=%KUBE_MASTER% --token=%KUBE_TOKEN% --insecure-skip-tls-verify=true

kubectl は curl でダウンロードするだけなので簡単です。現在のデプロイメントに対してイメージを更新するコマンドは kubectl set image になります。

オプションとして --server と --token を追加して、Kubernetes のマスターの URL とさっき作成したトークンを渡します。証明書の検証が問題になるので --insecure-skip-tls-verify=true を指定してスキップします。

AppVeyor で実際にビルド

appveyor.yml の修正を GitHub にコミットして、実際に AppVeyor でビルドを行いました。kubectl の実行結果から成功したことが分かります。たったこれだけでアップデートが行われます。

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

アップデート中にダッシュボードを確認すると、新しいレプリカセットとポッドが作成されています。

既にベースイメージは pull されているので、コンテナの起動は非常に高速です。

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

アップデートが完了したら、ブラウザで外部エンドポイントにアクセスしてみます。アプリケーションに違いがないと、本当にアップデートが行われたのか確認しにくいので、テキストを少しだけ変えておきました。

例によって Razor のプリコンパイルを行っていないので、起動に少し時間がかかりますが表示されます。拍子抜けするぐらいあっさりと AppVeyor からのデプロイが行えました。

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

ちなみに GitHub に push してから AppVeyor でのビルドが完了するまで 2 分ほどです。Docker Hub よりネットワーク的に近い Azure Container Registry を使うと pull は早くなりそうです。

今回は 1 エージェントかつ 1 レプリカで試しましたが、Kubernetes はまだ VMSS に対応していないみたいなので、エージェントを増やす手間がかかります。レプリカに関しては別の機会にまとめます。

Azure Container Service を使って Kubernetes と Windows Server Containers を試してみる

気が付いていなかったのですが、Azure Container Service のオーケストレータとして Kubernetes を選ぶと、Windows が選択できるようになっていたらしいです。もう 2 か月ぐらい前というのが驚きです。

まだ Public Preview になってないだろと思っていたら、ちゃんとドキュメントもありました。確か Swarm が Private Preview だったはずなんですが、いったいどこに行ってしまったのやら。

Windows Server Containers が使えるコンテナサービスを待望している人間としては、これは試しておかないといけないと思ったので、実際にクラスタを作成して試します。

Kubernetes クラスタを作成

Azure Portal から ACS を作成する際に Kubernetes を選ぶのは必須です。

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

例によって Japan East は VM が高いので、少し安い Japan West を選んでおきました。

次に Kubernetes のマスター向け設定を行います。マスターは Linux で動作するので SSH の公開鍵が必要です。そして Kubernetes が Azure のリソースを操作するために必要なサービスプリンシパルも設定します。

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

サービスプリンシパルは Azure CLI 2.0 を使うと簡単に作れます。*1

最後はエージェントの設定なので、ここで Windows を選びます。Windows を選ぶと RDP で接続するための認証情報を入力する必要があるので、適当に埋めておきます。

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

VM のサイズは中途半端にけちると苦労するので、デフォルトのままにしておきました。これでデプロイすると、Windows Server Containers 対応の Kubernetes が上がってきます。

Kubernetes への接続

Kubernetes への接続を行うためには kubectl と認証情報のダウンロードが必要らしいです。幸い Azure CLI 2.0 を使うと簡単にダウンロード出来るので、ドキュメントを紹介しておきます。

手元の PC には Azure CLI 2.0 を入れていなかったので、手動で kubectl をダウンロードして認証情報も SCP で拾ってきました。kubectl は単一の実行ファイルなので楽ですね。

kubectl と認証情報の設定が終わったので、接続テストとしてノードの情報を確認しておきました。

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

マスターとエージェントの情報が返ってきたので、認証情報に問題がないことが確認できました。

最初からコマンドで全て操作するのはしんどいので、Kubernetes のダッシュボードを使います。kubectl の proxy コマンドを使うとダッシュボードへの接続が行えます。

kubectl proxy

表示されたアドレスにブラウザでアクセスすると、Kubernetes のダッシュボードが表示されます。

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

Azure Container Service のドキュメントでは YAML ベースでデプロイを行っていましたが、折角なのでダッシュボードを使って試します。

アプリケーションをデプロイ

Kubernetes の用語については説明を省きますが、基本的に画面の指示通りに進めていけば問題ないです。

ナビゲーションからノードを選択すると稼働中のインスタンスとメトリックを確認できます。ECS はメトリックの表示に対応していなかったですが、Kubernetes はちゃんと確認することが出来て良いですね。

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

それはともかく、まずはアプリケーションをデプロイしてみます。デプロイするのは前回 AppVeyor で作成した ASP.NET MVC アプリケーションのイメージです。

JSON / YAML のアップロードも出来ますが、UI でポチポチ設定してみます。

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

重要な設定としてはサービスを外部にして、ターゲットポートを 80 に設定することです。

外部にしないと外からアクセス出来なくなりますし、作成したイメージは 80 でリクエストを待機しているので、ターゲットポートを間違えると繋がりません。

実際に配備を行うと、最初は例によってイメージの pull で時間がかかりました。これは ACS で使われている Windows Server 2016 のイメージが古いのが最大の原因だと思われます。

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

使われている Windows Server 2016 と Docker のバージョンは AppVeyor と比べて古いものだったので、公式らしく最新に追従する姿勢を見せてほしいところです。

ワークロードを選択すると、一度にステータスの確認が出来るので便利です。サービスを含め全てが緑色になればデプロイ完了なので、外部エンドポイントが表示されるようになります。

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

この外部エンドポイントは Azure Load Balancer を指しています。Load Balancer と Public IP Address は Kubernetes によって自動的に作成されていました。

外部エンドポイントにアクセスすると、前回作成した ASP.NET MVC アプリケーションが表示されました。

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

前に試した ECS よりも Kubernetes の方が Windows Server Containers への対応が進んでいる印象を受けました。まだ対応自体はプレビューですが、ダッシュボードから操作が行えるのは好印象です。

そろそろ Azure Container Service も Managed Disk を使って、いい感じにリソースを整理して欲しい気持ちでいっぱいです。あとベースイメージのバージョンアップは必須だと思います。

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:個人的にはちゃんと動かないイメージを生焼けと呼んでます。どうでもいい話だった。

AppVeyor が Windows Server 2016 に対応したので Docker を使うための下調べをする

2 か月ほど前になりますが、AppVeyor が Visual Studio 2017 と Windows Server 2016 が使えるワーカーイメージの提供を開始しました。

AppVeyor に限らず Windows Server 2016 対応はどのサービスも遅い気がしますね。

既に試している人もいますが、Docker 周りの状況も当時と変わってきているので改めて調べます。

最終的な目標は AppVeyor 上で ASP.NET アプリケーションの Docker Image をビルドして、Docker Hub や Azure Container Registry にプッシュして、ECS や ACS で使うことです。

Windows Server Containers の場合はベースイメージが大きいので、実用的かどうか含め調べます。

インストールされている Docker

まずは AppVeyor VM 上の Docker を確認するために docker info を実行してみました。ちなみに有料プランを契約しているので、ちょっと良い VM が用意されている状態です。

Windows Server 2016 の最新バージョンが使われていて、Docker のバージョンも 17.03.1-ee と新しいものがインストールされています。

> docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 2
Server Version: 17.03.1-ee-3
Storage Driver: windowsfilter
 Windows: 
Logging Driver: json-file
Plugins: 
 Volume: local
 Network: l2bridge l2tunnel nat null overlay transparent
Swarm: inactive
Default Isolation: process
Kernel Version: 10.0 14393 (14393.1066.amd64fre.rs1_release_sec.170327-1835)
Operating System: Windows Server 2016 Datacenter
OSType: windows
Architecture: x86_64
CPUs: 2
Total Memory: 1.464 GiB
Name: APPVYR-WIN
ID: MNR6:QBA5:QSF7:TNY2:G63V:WXA6:4TXI:CP5T:5B3B:TFBF:JLUV:LQVB
Docker Root Dir: C:\ProgramData\docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

Windows Server 2016 の 4 月アップデートが適用されているので、Docker Swarm のサポートが改善していたりします。詳細は KB4015217 やブログに載ってました。

Improved the Host Network Service (HNS) to support an overlay network driver for use on Windows Server 2016 to connect containers across hosts using Docker Engine in Swarm Mode.

https://support.microsoft.com/en-us/help/4015217/windows-10-update-kb4015217

Docker Swarm を CI で使うかと言われると使わないですが、最新に追従する姿勢は好感が持てます。

pull 済みのイメージ

docker images を実行して、既に pull されているイメージがあるのか確認してみました。Azure と同様に windowsservercore と nanoserver の最新バージョンが、予め pull されていました。

> docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
microsoft/windowsservercore   latest              590c0c2590e4        2 weeks ago         10.1 GB
microsoft/nanoserver          latest              a943c29f0046        2 weeks ago         1.01 GB

AppVeyor の Platform Update を見ると、ワーカー VM の更新と同タイミングでイメージも更新してくれているようです。これはかなり安心して使うことが出来そうです。

tag は特定バージョンを指定せずに latest で問題なさそうです。これは良さそう。

別のイメージを pull する

pull されていない aspnet などのイメージを使う場合にどのくらい時間がかかるのかと、一度 pull したイメージはキャッシュされて次からすぐに使えるのかを確認してみます。

実際に docker pull microsoft/aspnet を実行したところ、1 分ほどで完了しました。

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

自宅の物理マシンで実行した場合は 30 秒ほどなので、そこまで極端に遅くはないという印象です。

同じ処理を 5 回繰り返しましたが、毎回 pull が実行されていたのでキャッシュに関してはあまり期待できない気がしました。運よく pull 済みのマシンに当たれば、素早く処理できるかも知れませんが未確認です。

Dockerfile からビルドする

適当に FROM だけ書いた Dockerfile を用意して docker build を実行してみました。

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

当然ながらすんなりと動作して、イメージが作られました。ここまで確認すれば、後は Container Registry に push するぐらいなので遊べるようになりそうです。

コンテナをデプロイして実行する

最後にド定番の .NET Core のサンプルアプリをデプロイして、サクッと実行してみました。

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

Nano Server ベースなので pull から実行まで 20 秒かかりませんでした。AppVeyor で楽しい Windows Server Containers 生活が送れそうな気が少ししてきました。

Surface Pro 4 に Windows 10 Creators Update をクリーンインストールしてみた

MacBook Pro の Boot Camp 環境だと Creators Update へのクリーンインストールが問題になるらしいので、仕方なくサブ環境の Surface Pro 4 を先に Creators Update に更新することにしました。

価格改定で安くなった時に買った Surface Pro 4 が活躍です。

Visual Studio 2017 のインストールとユーザープロファイルを作り直したかったので、クリーンインストールにしています。何となく USB ドライブ作ってますが、最近だと要らないのかも。

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

MSDN から ISO を落としておきましたが、同じものを Windows 10 のダウンロードページから落とせる気がします。ISO をマウントしてコピーするだけなので簡単です。

Surface Pro 4 のクリーンインストールする前に、必要なドライバーをダウンロードしておきます。検索したら、丁度 Creators Update と同じタイミングで新バージョンがリリースされていました。

Creators Update 向けにドライバも色々とアップデートされたみたいです。

割と未だにブルースクリーンが頻発するので、そろそろ改善して欲しい気がします。

Surface Pro 4

  • Surface System Aggregator Firmware (v103.1610.256.0) resolves screen brightness issue when devices come out of sleep.
  • Intel(R) Precise Touch Device (v1.2.0.83) improves system stability and performance.
  • Surface Integration (v1.1.121.0) adjusts system hibernation defaults.

ダウンロードセンターから Pro 4 の場合は SurfacePro4_Win10_15063_1701601_0.msi をダウンロードすれば良いみたいです。基本的に zip をダウンロードするより msi の方が簡単です。

Download Surface Pro 4 Drivers and Firmware from Official Microsoft Download Center

インストールを始めると、噂通り Cortana が喋ってきて少し煩かったので、途中からミュートにして進めました、セットアップ時に Wi-Fi に接続してアップデート確認とか昔はなかった気がしました。

大体 15 分ぐらいでインストールは終わった気がします。

f:id:shiba-yan:20170408195140p:plain:w700

ダウンロードしておいた Surface Pro 4 のドライバーをインストールすると、同時に UEFI もアップデートされました。なので再起動必須で少し時間がかかりました。

ドライバーインストール後 Wi-Fi が繋がると、更に Windows Update でドライバーがアップデートされたっぽいです。Windows Update の履歴が分類別になってわかりやすくなりました。

f:id:shiba-yan:20170408194941p:plain:w600

当然ながら Surface Pen / Type Cover も問題なく使えるようになってます。そろそろ Surface Dial 対応のアップデートとか来て欲しいですが、もう来ない気もしてきました。

f:id:shiba-yan:20170408194952p:plain:w550

まだ Visual Studio 2017 を入れたぐらいですが、トラックパッドのジェスチャーが多くなった気がします。

他にも High DPI 周りが良くなったらしいので、Surface Pro 4 を使って体験したいです。

Windows Server Containers で利用する Docker Image のバージョン管理が難しい

最近はまた Windows Server Containers の実運用に関して、いろいろと考えたり調べたりしているのですが、Windows では絶対に避けられないものとして Windows Update があります。

そして現時点での Windows Server Containers には以下のような要件があります。

Windows Server コンテナーは、ビルド番号が異なると起動をブロックされます (例: 10.0.14300.1030 (Technical Preview 5) と 10.0.14393 (Windows Server 2016 RTM))。 ビルド番号が一致し、リビジョン番号が異なる場合は、起動をブロックされません (例: 10.0.14393 (Windows Server 2016 RTM) と 10.0.14393.206 (Windows Server 2016 GA))。 ただし、技術的にはブロックされませんが、これは状況によっては正しく機能しない可能性がある構成であるため、運用環境ではサポートできません。

Windows コンテナーの要件 | Microsoft Docs

ドキュメントの内容を解釈すると、Windows Server Containers ではリビジョンまでホストとコンテナのバージョンを一致させないと、正しく動かない可能性があるし運用環境では実質使えないということでしょう。

ここで Docker の罠が出てくるわけです。普通に microsoft/windowsservercore と指定すると latest タグのイメージが落ちてくるので、リビジョンはその時の最新になり固定できません。現時点では面倒でもタグまでちゃんと指定するべきということなのでしょう。

# Windows Server Core のイメージを利用する
FROM microsoft/windowsservercore:10.0.14393.953

# IIS までインストールされたイメージを利用する
FROM microsoft/iis:windowsservercore-10.0.14393.953

# ASP.NET 4.6.2 までインストールされたイメージを利用する
FROM microsoft/aspnet:4.6.2-windowsservercore-10.0.14393.953

当然ながら Windows Update でリビジョンが変わった場合には、同様に変更する必要があります。

オンプレの仮想環境であれば、自分でバージョンやアップデートのタイミングをある程度決められるので latest でも良いかもしれないですが、Azure や AWS の場合は少し注意が必要そうです。

Azure の場合

Azure にある Windows Server 2016 with Containers を利用すると、予め Windows Server Core と Nano Server が pull された状態で起動することが出来ますが、タグが latest になっているので扱いにくいです。

最近の Windows Server Core だと多少は差分が利用されるみたいなので、5GB 落とし直しにはならないみたいですが時間はかかります。

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

Dockerfile で latest を指定したイメージを実行しようとすると、イメージを作成した時点での latest になるので奇跡的にバージョンが一致していないと pull し直しになってしまいそうです。

ある意味公式である Azure VM のイメージがこれだと、正直なところ不安になってきます。

AWS の場合

EC2 の Windows Server 2016 Base with Containers ではイメージが pull されていないので、そのまま ECS のベースイメージとして使うと全てのインスタンスで pull が走ってしまって時間がかかります。

予め pull 済みの AMI を作っておいた方が良さそうです。User Data で pull と sysprep までやらせます。

function Get-OSVersion() {
    $buildLabEx = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\').BuildLabEx
    $osBuild = $buildLabEx.Substring(0, $buildLabEx.IndexOf(".", 6))

    return "10.0." + $osBuild
}

docker pull microsoft/windowsservercore:$(Get-OSVersion)
docker pull microsoft/iis:windowsservercore-$(Get-OSVersion)
docker pull microsoft/aspnet:4.6.2-windowsservercore-$(Get-OSVersion)

docker pull microsoft/nanoserver:$(Get-OSVersion)
docker pull microsoft/iis:nanoserver-$(Get-OSVersion)

cd "$env:ProgramData\Amazon\EC2-Windows\Launch\Scripts"
.\InitializeInstance.ps1 -Schedule
.\SysprepInstance.ps1

ホストとコンテナのバージョンは合わせる必要があるので、頑張ってレジストリから取得するようにしています。ECS クラスターを作成するのは面倒だったので、普通に EC2 のインスタンスを立ち上げました。

docker images を実行すると、各ベースとなるイメージが pull 済みになっているのが確認できます。

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

AMI で用意されている Windows Server 2016 のバージョンと同じになっていることも確認できました。

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

課題としては Windows Update のタイミングでリビジョンが上がるという点ですが、こればっかりは Windows Update の時に AMI を作り直して入れ替えるぐらいしかない気がしました。

リビジョンをまで指定しないといけないのは非常に扱いにくいですが、カーネルを共有している以上仕方ない部分だと思いました。docker pull が賢くなればましになるかもしれないですが、今はこれで精いっぱい。

UWP アプリケーションの収益を PayPal で受け取ってみた

最近はちょくちょく UWP アプリケーションを開発してきて、そろそろ収益の受け取りについて調べないといけないと思ったのがきっかけです。PayPal で受け取りました。

色々と人に聞いたり、ネットで調べたりしたのですが情報が出てこなかったので、体験談を書いておきます。

PayPal ビジネスアカウントを開設

まずは支払いを受け取るための PayPal アカウントを開設しました。一応個人事業主ということになっているので、ビジネスアカウントを開設しておきました。

開設自体は必要な情報を入力して、本人確認書類(免許証とか)を送信すれば、PayPal 側で審査が行われて、後ほど書留でアクティブ化用のパスワードが送られてきます。

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

地味に時間がかかってしまうので、早めに開設した方が良さそうです。私の場合は 2 週間近くかかりましたが、全ての設定を終えていつでも収益を受け取れる状態になっています。

受け取りアカウントを PayPal に

Windows Developer Center の受け取りアカウント設定から PayPal のアカウントを追加します。

メールアドレスと名前を入力するだけなので簡単ですが、PayPal 側の表記に合わせておかないと、めんどくさいことになりそうな気がしています。

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

登録が終わればアカウント設定に情報が表示されます。支払い保留の設定はオフにします。

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

これで収益がしきい値を超えている場合には、毎月 15 日に支払処理が行われます。

収益の振り込みを確認

月初めの方に入金可能な収益が確定されるようになっています。そして 15 日になると実際に PayPal にて支払いが行われました。見た感じ手数料は引かれていないようです。

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

支払いが作成されても、実際に決済が行われて資金の移動が出来るようになるまで 3-5 営業日ぐらいかかることがあるようです。今回は 2 営業日で決済が完了しました。

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

実際に決済が行われましたが、手数料がかかっていないように見えます。

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

PayPal で支払いを受け取ったことはないですが、手数料がかからないのはちょっと怪しいです。

手数料としきい値について

Windows Store に有料アプリや、広告付きのアプリを公開している場合に大体最後の最後で苦労するのが、この収益の受け取りだと思います。単純に銀行振り込みを利用すると、場合によってはとんでもない手数料がかかることがあります。

受取りアカウントの設定と税関連の書類 - UWP app developer | Microsoft Docs

PayPal を利用した支払いの受け取りに場合には 4% の手数料がかかる*1ようですが、今回は 0 円表示ですし実際に引かれずに Dev Center の表示通りの額でした。

受け取ることが出来る収益のしきい値が決まっていますが、Windows Store での売り上げの場合は $25 から、広告収入の場合は $50 から受け取れるようになっています。

支払しきい値、方法、期間 - UWP app developer | Microsoft Docs

銀行振込の場合は Windows Store の売り上げは $200 以上ないと振り込まれないので、PayPal を使った場合にはすぐに受け取れる可能性があります。

とりあえずこの売り上げで明日は寿司を食べてこようかと思います。