ASP.NET CoreアプリをAzure App Serviceに配置して、Production / Stagingのスワップまで試す

今回のシナリオとしては以下を想定しています。

  1. VS2015でASP.NET Coreアプリを作成
  2. 構成情報として appSettings.json を用意 *また、Staging環境用の appSettings.Staging.json、開発環境用の appSettings.Development.json を用意
  3. AzureのApp Serviceにデプロイ
  4. App Serviceに Staging 環境用スロットを追加
  5. Staging環境にデプロイ
  6. Staging -> Production をスワップ

1.VS2015でASP.NET Coreアプリを作成

まずは Visual Studio 2015 で簡単なASP.NET Coreアプリを作成します。

空のテンプレートを選択し、右下の「クラウドにホストする」をチェックします。

f:id:daigo-knowlbo:20160606123759p:plain

f:id:daigo-knowlbo:20160606123917p:plain

今回はスロット間のスワップを想定しているのでプランは「Standard」もしくは「Premium」である必要があります。
f:id:daigo-knowlbo:20160606124121p:plain

以下のような感じで適当に設定を行い、作成ボタンをクリックします。

f:id:daigo-knowlbo:20160606124222p:plain

2.構成情報として appSettings.json を用意

VS2015により HelloWorkd Webアプリが自動生成されました。
構成ファイル「appSettings.json」を用意します。
Production環境とStaging環境、Development環境で異なる動作をさせたいので、appSettings.json および appSettings.staging.json、appSettings.Development.json の3つの構成ファイルを用意します。

appSettings.jsonは以下の通り。

{
  "ProductName": "I'm HelloAzureSlotWithCore!!",
  "Message":  "Mobile First! Cloud First!"
}

appSettings.Staging.jsonは以下の通り。

{
  "ProductName": "I'm HelloAzureSlotWithCore!! This is staging configuration setting."
}

appSettings.Development.jsonは以下の通り。

{
  "ProductName": "I'm HelloAzureSlotWithCore!! This is Development configuration setting."
}

次に Startup.cs を修正し、構成ファイルの読み込み及び、読み込んだ情報の画面への出力を実装します。
Startup.csの実装は以下の通り。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;

namespace HelloAzureSlotWithCore
{
  public class Startup
  {
    IConfiguration _config = null;

    public Startup(IHostingEnvironment env)
    {
      this._config= new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appSettings.json")
        .AddJsonFile("appSettings." + env.EnvironmentName + ".json", True)
        .Build();
    }

    public void Configure(IApplicationBuilder app)
    {
      app.Run(async (context) =>
      {
        string content =
        this._config["ProductName"] + "<br/>" +
        this._config["Message"];
        await context.Response.WriteAsync(content);
      });
    }
  }
}

開発環境から実行した結果は以下の通り。ProductName項目については appSetting.Development.json構成 がオーバーライド適用され、Message項目については appSettings.json で定義した値が取得されています。

f:id:daigo-knowlbo:20160606130753p:plain

3.AzureのApp Serviceにデプロイ

では作成されたアプリをAzure AppServiceにデプロイしましょう。
ソリューションエクスプローラ→プロジェクトのポップアップメニュから「公開」を選択します。

f:id:daigo-knowlbo:20160606130940p:plain

各種設定はデフォルトのままで「発行」をクリックします。
f:id:daigo-knowlbo:20160606131101p:plain

f:id:daigo-knowlbo:20160606131114p:plain

また、appSetting.jsonは上記手順で発行されないので、個別にソリューションエクスプローラから appSettings.json を選択し、「発行」メニューを選択します。

f:id:daigo-knowlbo:20160608090036p:plain

AzureポータルでApp Serviceを確認するとデプロイされたことを確認できます。

f:id:daigo-knowlbo:20160606211128p:plain

以下が実行画面です。appSettings.jsonの構成で動作していることが分かります。

f:id:daigo-knowlbo:20160607083048p:plain

4.App Serviceに Staging 環境用スロットを追加

ここまでの設定ではAzure App Serviceは1スロット構成として動作していました。このデフォルトスロットを Production 環境とし、追加で Staging スロットを作成することとします。
まず、はデフォルトのスロットを明示的に Production 環境としましょう。
Azureポータルを開き「App Service → HelloAzureSlotWithCore → すべての設定 → アプリケーション設定」を選択します。

f:id:daigo-knowlbo:20160608121151p:plain

「アプリ設定」項目に ASPNETCORE_ENVIRONMENT / Production 設定を追加して保存します。ここで設定した値は ASP.NET Coreアプリケーションでは「env.ContentRootPath」として取得する値となります。

f:id:daigo-knowlbo:20160607083602p:plain

次にStagingスロットを追加します。
Azureポータルから「App Service → HelloAzureSlotWithCore → すべての設定 → デプロイメント スロット」を選択します。

f:id:daigo-knowlbo:20160607083831p:plain

「スロットの追加」を選択し、名前を「Staging」としてOKボタンをクリックします。

f:id:daigo-knowlbo:20160607083923p:plain

「追加されたスロットを選択 → すべての設定 → アプリケーション設定」を選択します。

f:id:daigo-knowlbo:20160607084146p:plain

Productionスロットに行ったのと同様に アプリ設定 項目に、今度は ASPNETCORE_ENVIRONMENT = Staging として設定を追加します。

f:id:daigo-knowlbo:20160607084220p:plain

5.Staging環境にデプロイ

では、Staging環境にアプリケーションをデプロイします。その前に、これからデプロイするStaging環境のアプリを、そのあとでProduction環境にスワップすることを想定して、Startup.Configuration()の実装を以下のように修正しておきます。つまりアプリケーションの実装をバージョンアップさせておきます。

public void Configure(IApplicationBuilder app)
{
  app.Run(async (context) =>
  {
    string content =
      "This is new version!!" + "<br/>" +
      this._config["ProductName"] + "<br/>" +
      this._config["Message"];
    await context.Response.WriteAsync(content);
  });
}

VS2015にてソリューションエクスプローラ上のプロジェクトをマウス右ボタンメニュー → 公開を選択します。
「<新しいカスタムプロファイル>」を選択し、「HelloAzureSlotWithCore_Staging」というプロファイルを追加します。これはStaging環境へのデプロイ用プロファイルとなります。

f:id:daigo-knowlbo:20160607084700p:plain

f:id:daigo-knowlbo:20160607084749p:plain

「発行先の選択」から「Microsoft Azure App Service(A)」を選択します。

f:id:daigo-knowlbo:20160607084927p:plain

以下のようにツリーを展開すると「Staging」スロットが表示されます。これを選択してOKボタンをクリックします。

f:id:daigo-knowlbo:20160607084948p:plain

では、アプリケーションをStaging環境に発行しましょう。

f:id:daigo-knowlbo:20160607085042p:plain

appSetting.jsonも発行します。

f:id:daigo-knowlbo:20160608090036p:plain

実行画面は以下の通りです。URLは「http://helloazureslotwithcore-staging.azurewebsites.net/」という staging 用アドレスであり、実行結果を見ても「This is new version!」の文字から新しいバージョンのアプリケーションであり、構成情報も appSettings.staging.json が適用されていることを確認できます。

f:id:daigo-knowlbo:20160608085627p:plain

念のため、Production環境の「http://helloazureslotwithcore.azurewebsites.net/」にアクセスしてみましょう。最初にデプロイしたアプリケーションが動作していることが確認できます。

f:id:daigo-knowlbo:20160608085815p:plain

6.Staging -> Production をスワップ

では、staging環境の新しいアプリケーションを production環境にスワップしてみます。
Azureポータル画面で「App Service → HelloAzureSlotWithCore → スワップ」を選択します。

f:id:daigo-knowlbo:20160608090319p:plain

ソースは「Staging」、展開先は[Production」としてOKボタンをクリックします。

f:id:daigo-knowlbo:20160608090357p:plain

スロットの交換が始まります。

f:id:daigo-knowlbo:20160608090441p:plain

スワップ完了後、Production環境の「http://helloazureslotwithcore.azurewebsites.net/」にアクセスしてみましょう。

f:id:daigo-knowlbo:20160608121705p:plain

新しいアプリケーションであることを示す「This is new version!」の文字、そしてProduction環境用 appSettings.json 構成ファイルが適用されていることを示すProductName値(I'm HelloAzureSlotWithCore!!)を確認することができます。

その他・・・

と、スムーズに行ったかのような説明を記述しましたが・・・同じ手順で行っているつもりでも、何度かうまく発行できないことがありました。後から考えるとブラウザのキャッシュのクリアが問題だったような気がしますが・・・あと、サンプルのようなcontext.Response.WriteAsync()だけの記述だと文字コードの指定がないので、This is new version"の部分を日本語にするとブラウザで実行した際にShift-jis扱いを受けて文字化けすることがあるのでご注意を。

※dotnetConf 2016 で ASP.NET Core RTMが 2016/6/27 と発表されたようですね。