しばやん雑記

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

ASP.NET 5 アプリケーションが Kudu によってどのようにデプロイされるのか調べた

Azure 界の抱かれたい男 No.1 こと @kosmosebi に「ASP.NET 5 を Websites で動かす方法を調べやがれ」と言われたので、Azure 界で生きていくために頑張って調べました。

No.1 とムッシュに逆らうと生きていけないのがこの業界の鉄則です。

1.0.0-beta1 がデフォルト

ASP.NET 5 への対応が行われたコミットを見つけたので、この差分を見るのが手っ取り早いと思いました。

Adding support for ASP.NET 5 projects in Kudu · projectkudu/kudu@d60eab7 · GitHub

No.1 が詰まっていた原因は 1.0.0-beta2 のランタイムを明示的に指定する必要があったという話でしたが、このコミットは 2 ヶ月以上前なので当然ながらデフォルトの KRE バージョンは 1.0.0-beta1 です。

ASP.NET 5 (CTP5) のプロジェクトを Azure Websites で動かす | ブチザッキ

とりあえずこれで動いたので良かったとなればいいんですが、そう甘くないのがこの業界。

Kudu のデプロイスクリプト

基本的に Git などの外部リポジトリ連携でデプロイした場合には、Kudu が自動的にプロジェクトの種類を判別し、デプロイスクリプトを生成して実際にデプロイを行います。難しいことないです。

ログに使われたスクリプトのパスが残るので、ASP.NET 5 に関係する部分だけを引っ張ってきました。

echo Handling ASP.NET 5 Web Application deployment.

:: Remove wwwroot if deploying to default location
IF "%DEPLOYMENT_TARGET%" == "%WEBROOT_PATH%" (
    FOR /F %%i IN ("%DEPLOYMENT_TARGET%") DO IF "%%~nxi"=="wwwroot" (
    SET DEPLOYMENT_TARGET=%%~dpi
    )
)

:: Remove trailing slash if present
IF "%DEPLOYMENT_TARGET:~-1%"=="\" (
    SET DEPLOYMENT_TARGET=%DEPLOYMENT_TARGET:~0,-1%
)

:: 1. Install KRE
call :ExecuteCmd PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%SCM_KVM_PS_PATH%' %*" install %SCM_KRE_VERSION% -%SCM_KRE_ARCH% -runtime %SCM_KRE_CLR% %SCM_KVM_INSTALL_OPTIONS%
IF !ERRORLEVEL! NEQ 0 goto error

IF EXIST "%USERPROFILE%\.kre\run-once.cmd" (
    CALL "%USERPROFILE%\.kre\run-once.cmd"
    DEL "%USERPROFILE%\.kre\run-once.cmd"
)

:: 2. Run KPM Restore
call kpm restore "%DEPLOYMENT_SOURCE%" %SCM_KPM_RESTORE_OPTIONS%
IF !ERRORLEVEL! NEQ 0 goto error

:: 3. Run KPM Pack
call kpm pack "D:\home\site\repository\src\WebApplication3\project.json" --runtime "%USERPROFILE%\.kre\packages\KRE-%SCM_KRE_CLR%-%SCM_KRE_ARCH%.%SCM_KRE_VERSION%" --out "%DEPLOYMENT_TEMP%" %SCM_KPM_PACK_OPTIONS%
IF !ERRORLEVEL! NEQ 0 goto error

:: 4. KuduSync
call %KUDU_SYNC_CMD% -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
)

やっていることは結構シンプルで以下のような手順になってます。

  1. KRE をインストール
    • 初回は run-once.cmd も実行
  2. kpm restore を実行
    • NuGet / npm から必要なパッケージを復元
  3. kpm pack を実行し、結果をテンポラリに書きだす
  4. kuduSync でテンポラリから wwwroot にコピー

このデプロイスクリプトを作っているのは KuduScript というサブプロジェクトなので、そっちのリポジトリを見るとテンプレート化されたスクリプトを発見できます。

projectkudu/KuduScript: Kudu's deployment s... - GitHub

Kudu の他に xplat-cli でもこれが使われている感じです。

kpm pack について

デプロイスクリプトの中で割と謎だった kpm pack については GitHub Wiki に説明が書いてありました。

Home · aspnet/Home Wiki · GitHub

どうやら kpm pack を実行すると、アプリケーションの実行に必要なパッケージなどを全て含んだ形にしてくれるようです。実際に Visual Studio 2015 で発行した時にも、事前に kpm pack が実行されていました。

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

kpm pack 後のファイルを Visual Studio ではデプロイしていたため、Git を使った時のようにバージョンの問題が発生しないという話でした。

ちなみに kpm pack した結果、アプリケーションはポータブルな形になるため、開発マシンから別のマシンにコピーしてコマンドで起動することが出来ます。

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

CoreCLR を選んだ場合は .NET Framework のバージョンにも依存しなくなるはずです。