読者です 読者をやめる 読者になる 読者になる

しばやん雑記

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

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

Windows Docker

最近はまた 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 で受け取ってみた

Windows UWP

最近はちょくちょく 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 を使った場合にはすぐに受け取れる可能性があります。

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

.NET Core のバージョンが難しい

C#

ちょっと前に .NET Core のバージョンがよくわからないという話題が Twitter で上がりました。

おーみさんとにぃにが分からないのなら、みんなわからないのではという感があるのと、自分も正直よくわからなかったので理解を兼ねて調べました。バージョニング失敗してるとしか思えない。

ダウンロードページでは SDK と Runtime で分かれています。SDK は .NET Core 1.0 と 1.1 を含んでいることが分かるのですが、ダウンロードしたファイルには 1.0.1 とあります。

.NET Core Downloads

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

Linux 版の .NET Core は 1.0.4 と 1.1.1 でダウンロードリンクは分かれていますが、Ubuntu と RHEL では 10 だったり 1.0.1 だったりと混乱しそうなバージョンになってます。

.NET Core downloads - Linux

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

流石にこれは混乱するので、いいタイミングだと思ったので調べました。分かったことは我々が .NET Core と呼んでいるものは、実際は 3 つに分かれているということでした。

現時点でのコンポーネントとバージョンを適当に挙げます。

  • .NET Core Shared Framework Host
    • 1.1.0
  • .NET Core SDK
    • 1.0.1
  • .NET Core Runtime
    • 1.0.4 (LTS) / 1.1.1 (Current)

この中で意識しておかないといけないのは、多分 SDK と Runtime のバージョンです。

.NET Core Shared Framework Host は dotnet.exe 自体を指しているようです。この時点で分かりにくい。

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

そして dotnet にオプションを付けて呼び出すと .NET Command Line Tools が呼び出されるようです。しかし dotnet をオプション無しで実行した時の説明が多分間違っている。

Common Options:
  --help                           Display .NET Core Shared Framework Host help.
  --version                        Display .NET Core Shared Framework Host version.

.NET Core Shared Framework Host のバージョンと書いてあるのに、実際には 1.0.1 が表示されるので SDK のバージョンを表示しているようです。かなり混乱してきます。

確実な方法は --info を付けて呼び出すことです。詳細な情報が表示されます。

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

SDK という呼び方が分かりにくさを加速させている感じがしますが、実体は .NET CLI でした。

インストールディレクトリを見ると、ちゃんと host / sdk / shared と分かれています。

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

SDK の 1.0.0 はどこに行ったのかは、多分疑問に思ってはいけないやつです。

また shared って何だという感じがしてきますが、ここに .NET Core のランタイムが入っています。バージョン番号も見慣れたものですね。

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

dotnet.exe のオプションに --fx-version というのがあるので 1.0.4 と指定すれば、そのバージョンで実行できるのかもしれないです。しかし殆どの場合は project.json や csproj で指定するので使う場面があるのかは謎。

ちなみに Docker Image はランタイムのバージョンで統一されているので迷うことはないです。

https://hub.docker.com/r/microsoft/dotnet/

.NET Core 1.1.1 が使いたい場合は 1.1.1-runtime / 1.1.1-sdk などのタグを選ぶだけです。

個人的には結局のところ、常に最新版を入れておけば何とかなるだろうという結論に達しました。CoreFX のバージョンを入れるともっとやばいことになるのですが、そういうことはにぃにに任せたいと思いました。