.NET Framework 2.0 の WebForm アプリを Azure Service Fabric で動かす

## 考え方

基本的に[チュートリアル](https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-host-app-in-a-container#containerize-the-application)のまんまです。
以下を実施する事で、.NET Framework 2.0 でも動作させる事が出来ます。

- コンテナオーケストレーターサポートの追加時にターゲットフレームワークを 4.5 以降に変更（その後 2.0 に戻す）
- Dockerfile のベースイメージを microsoft/aspnet:3.5 に変更



## 確認用アプリケーション

動作確認用の WebForm アプリケーションを用意します。

プロジェクトテンプレートから0「ASP.NET Web アプリケーション (.NET Framework)」を選択し、フレームワーク「.NET Framework 2.0」で新規プロジェクトを作成します。

![2018-10-23_19h02_37.png](https://qiita-image-store.s3.amazonaws.com/0/64309/e80d98fd-7bd5-0fe2-36b4-eff6b99d63d4.png)

コードは以下のように。
ホスト名とランタイムバージョンを表示するだけです。

```csharp:WebForm1.cs
 namespace 
WebForm
 {
     public partial class WebForm1 : System.Web.UI.Page
     {
         protected void Page_Load(object sender, EventArgs e)
         {
             lblMachineName.Text = Environment.MachineName;
             lblRuntimeVersion.Text = System.Reflection.Assembly.GetCallingAssembly().ImageRuntimeVersion;
         }
     }
 }
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/960ddda0-75e9-d05e-4024-2498fde4b49e.png)

以下、このアプリを Service Fabric 上で動くようにしていきます。


## フレームワークバージョンの変更

プロジェクトのプロパティを開き、ターゲットフレームワークを 4.5 以上に設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/bca2f775-3b03-dba7-59fb-688fc7dcbe8c.png)

※4.5 未満では、この次のコンテナオーケストレーターサポート追加時にエラーが発生します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/cb4ed2c4-2bd3-17a8-39db-893fee382976.png)



## コンテナオーケストレーターサポートの追加

WebForm のプロジェクトを右クリックして、「追加」->「コンテナーオーケストレーターサポート」から、「Service Fabric」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/071e5c76-8cfc-6b7b-10ca-68179a07f9f6.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/5cba3ced-6e03-f15e-af35-bd323bd4e348.png)


コンテナーオーケストレーターサポートを追加すると、「(プロジェクト名)Application」というプロジェクトが追加されます。
また、WebFrom プロジェクトには Dockerfile （と、config ファイル）が追加されます。

![2018-10-22_21h19_25.png](https://qiita-image-store.s3.amazonaws.com/0/64309/7593f460-60c2-9943-17e0-52bc4f5f2a2f.png)


実行すると、ローカルの Service Fabric ランタイム上で WebForm アプリが起動します。
※初回は ~~クソ重い~~ Windows Server のコンテナイメージがダウンロードされます。通信量を気にしなくて良い環境で実行しましょう。

![2018-10-23_22h47_18.png](https://qiita-image-store.s3.amazonaws.com/0/64309/e54d83af-22ea-86c2-079d-d2cfc7eb1597.png)
![2018-10-23_22h47_40.png](https://qiita-image-store.s3.amazonaws.com/0/64309/8106a1b5-adea-b335-8dae-797ff70ee532.png)


URLが実行しているPCのホスト名になり、`Environment.MachineName` の値がコンテナIDになっている事がわかります。
当然ながらランタイムは 4.0 ですね。





### .NET Framework 2.0 で動かす

プロジェクトのターゲットフレームワークを 2.0 に戻します。

![2018-10-25_15h57_55.png](https://qiita-image-store.s3.amazonaws.com/0/64309/b6549231-57ec-aeb9-a640-37ef193db56b.png)


また、プロジェクトに追加された Dockerfile を開き、使用するベースイメージを 3.5 に変更します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/fa63b3bd-8e38-ca72-41f1-cd15c5b85dff.png)

これを実行すると、.NET 2.0 で動いていることが確認できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/b1e0b9f5-019b-fb96-8f61-2bbe59811f17.png)



### Azure へのデプロイ

#### Azure Service Fabric クラスターの作成

こちらもチュートリアル通りに VisualStudio から作成していきます。
まず Service Fabric プロジェクトを右クリックして「発行」を選択し、「Service Fabric アプリケーションの発行」フォームを開きます。

「接続のエンドポイント」で「新しいクラスタの作成」を選択します。

![2018-10-25_15h28_34.png](https://qiita-image-store.s3.amazonaws.com/0/64309/b42afb5b-e93c-f171-a3f6-bb104ddb4292.png)


クラスター情報はお使いの環境に合わせて任意に設定してください。

![2018-10-25_15h54_35.png](https://qiita-image-store.s3.amazonaws.com/0/64309/b7e2ae5f-b3b4-23a6-1578-092cd4730e58.png)
![2018-10-25_15h54_50.png](https://qiita-image-store.s3.amazonaws.com/0/64309/893a9ef4-7643-465a-eb5b-96df5a7b73e1.png)


仮想マシンイメージには「WindowsServer2016-Detacenter-with-Containers」を選択します。
※2018/10/05 現在。コンテナのベースイメージと互換性のあるOSを選択します。詳細は [Windows Server コンテナーの OS とホスト OS の互換性](https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-get-started-containers#windows-server-container-os-and-host-os-compatibility) を参照してください。

![2018-10-25_15h55_27.png](https://qiita-image-store.s3.amazonaws.com/0/64309/50596ee0-2881-adbf-ab23-921b15eab521.png)


「詳細」タブのポートには、 PackageRoot\ServiceManifest.xml の Endpoint に指定されているポート番号を追加します。
※ローカル実行した際のポート番号と同じです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/015bad44-52cb-7192-12a7-d2182533aa9d.png)


全てのタブを正しく入力して「作成」すると Azure 上に Service Fabric クラスタが作成されます。
クラスタの作成にはかなり時間が掛かるので、接続可能になるまで気長に待ちましょう。

![2018-10-25_16h08_09.png](https://qiita-image-store.s3.amazonaws.com/0/64309/33edf464-dc22-8f36-079d-daede8ead46d.png)


#### コンテナレジストリの作成

PowerShell で [こちら](https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-host-app-in-a-container#create-a-container-registry) のスクリプトを実行してコンテナレジストリを作成します。
Azure Portal から作成しても構いません。

#### Service Fabric クラスターのデプロイ

VisualStudio から再度「Service Fabric アプリケーションの発行」フォームを開き、作成した Service Fabric クラスターのエンドポイントとコンテナレジストリを選択して「公開」します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/64309/ac5f73af-37b4-24bf-f932-eebac4e85cb7.png)


Azure 上の Service Fabric でも動きました！

![2018-11-03_21h58_27.png](https://qiita-image-store.s3.amazonaws.com/0/64309/36e2259f-0b32-62c7-9b44-83cee4aa6e17.png)




## まとめ

Service Fabric SDK を使う事で、.NET Framework 2.0 の WebForm アプリケーションでも簡単なオペレーションでコンテナ化する事ができます。
レガシーアプリに手を入れる事なく、「レガシーなまま」 PaaS 環境にシフトする事ができるのは嬉しいですね。

現実的には、起動の遅さ（これは Windows Server コンテナイメージがクソ程デカいのが原因だと思う）とか課題はあるでしょうが、いわゆる「リフト＆シフト」の一つの手段としてはアリじゃないかと思います。


## 参考

- [チュートリアル: Windows コンテナー内の .NET アプリケーションを Azure Service Fabric にデプロイする](https://docs.microsoft.com/ja-jp/azure/service-fabric/service-fabric-host-app-in-a-container#create-a-container-registry)
- [.NETアプリのクラウド移行～Azure Service Fabricを丁寧に (SlideShare)](https://www.slideshare.net/KazuyukiNomura/netazure-service-fabric)