今日は Windows Azure Advent Calendar jp: 2012 の9日目のネタをお送りします。
今日のお題というか今年のお題はですね、みなさんご存知、Windows Azure Web Sitesに関するちょっとイイ話です。
Windows Azure Web Sites はお手軽にWebサイトを立ち上げることができる、Windows Azureのサービスの1つです。なんと今ならリージョンあたり10個まで無料で作ることができます!(つまり今だと最大50サイト!)
これは有効利用するっきゃないですね!
というわけで、なんとなくあったら便利そうだなっていうWebアプリをWindows Azure Web Sitesでホストしちゃいましょう~!というのが今年の趣旨でございますー。
さてここで何をホストしよう?となるわけですが、個人的に今欲しいものをホストしてみようと思います。
ずばり、個人用NuGetサーバー!
何となくNuGetサーバー欲しいなと思ってもやもやしてて、どうせなら…ということで。
NuGet.Serverを改造しよう
で、NuGetサーバーで色々探してるとだいたい海外のサイトか、しばやん先生の記事にたどり着くので、そこを参考にまず見てみましょう。
ふむふむ、NuGet.Serverを使うと簡単にホストできそうだなーということでこいつを改造することにしましょう。
ソースはCodePlexにあるので、適当にForkしました。
改造するにあたり中身をいろいろ見てて、どうもNuGetサーバーはファイルシステムにパッケージファイルを保存してるみたいです。あれ?Feedとかどうしてるんだろ?と思ってよく見てみると、なんかファイルシステムを舐めてるだけなんですね。。。パッケージ増えたり負荷増えるとスケールしなさそう、もしくはしにくそうです。。。スケールとか考えないものなのだろうか(
パッケージの情報どうしてるんだろ?→ パッケージ全部開いて中のマニフェスト見てました\(^o^)/オワタ
これはシンドイ。もうちょっと何かメタデータの管理用の何かあると思ってたのに。
と嘆いてもしょうがないので、パッケージファイルそのものはAzureのBlobに、Feedなどに必要なメタデータはAzureのTableに放り込むことにしました。
なんかシリアライズできなさそうなクラスが根元にあったりパッケージの構造がややこしかったりしましたが適当にいじくりました。おかげでksコードな気がしないでもないですが。
仕組み的には以下のような感じです。
パッケージファイルそのものですが、BlobからWebSite上へダウンロード後クライアントに転送、とういのとSASつけてBlobから直接ダウンロード(リダイレクト)の2パターンを用意しました。
というのは無料のAzure Web Siteだと転送量が気になるところというのと、せっかくBlob使ってるんだからそっちから落とさせればいいじゃないという理由でリダイレクトするようにもしてます。Publicにしないのが目的なので、SAS付のURLをWebアプリ側で生成する感じですね。
今回、BlobとTableのアクセスはWindows Azure Storage Client 2.0を使ってますが、これがもともとのNuGet.Serverと相性が悪かったです。NuGet.Serverのサービスを公開するのにSystem.Data.Servicesを使ってたので入れ替えなきゃならんのですが、入れ替え後Azure上に持っていったら動かない。
どうもAzure Storage Clientで使ってるのはMicrosoft.Data.Servicesの5.0.2.0で、これがAzure上にないから見たい。でアセンブリはコピーするようにしても5.0.0.0がGACにあるから(?)うまくサービスを解決できなくてコケル、という感じでございました。
しょうがないのでWeb.configに以下のように書いて終了。
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.5"> <assemblies> <add assembly="Microsoft.Data.Services, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add assembly="Microsoft.Data.Services.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add assembly="Microsoft.Data.Edm, Version=5.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add assembly="Microsoft.Data.OData, Version=5.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> <add assembly="System.Spatial, Version=5.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </assemblies> </compilation> </system.web> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.Services" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.Services.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Spatial" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-5.0.2.0" newVersion="5.0.2.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
そのうち治るかな?
NuGetパッケージの作成
まぁそんなこんなで NuGet.AzureWebSite というベースができました。このまま適当に発行してもいいわけですがせっかくなので、NuGet.Serverと同じようにNuGetパッケージ化してしまいましょう。
パッケージ化はNuGet Package Templateという拡張機能があるので、こいつをインストールしてVisual Studioでいろいろいじります。
.nuspecファイル(XMLファイル)をいじって必要なファイルを放り込むだけですが。
今回、Windows Azure上にいろいろ放り込むのでアセンブリファイルのローカルコピーをTrueにしたりするのにinstall.ps1を少しいじってます。あとWeb.config.transformでWeb.configに追加するようにしたり、.ppでクラスを生成したりするようにしました。この辺は元のNuGet.Serverのパッケージとか見てそのまま流用してるわけですが。(install.ps1は独自)
というわけで作成したものがこちら。
PM> Install-Package NuGet.AzureWebSite
てなぐあい。
NuGet.AzureWebSiteの使い方
1. 空のASP.NET Webアプリケーションプロジェクトを作成します。
2. NuGetからNuGet.AzureWebSiteを追加します。
3. 必要なファイルが追加されます。
4. Windows Azure Web Siteを管理ポータルから作成して発行プロファイルをダウンロードします。
5. 発行を選択して、ダウンロードしたプロファイルをインポートします。
6. 管理ポータル上の「構成」タブの「アプリ設定」に以下の内容を追加し適宜設定します。
キー | 指定する値 | 備考 |
requireApiKey |
false または true | NuGetの管理にAPIキーが必要かどうかを指定します。Trueの場合はapiKeyに値を設定する必要があります。 |
apiKey |
任意の値 | 使用するAPIキーです。 |
azureStorageConnectionString |
Azure Storageへの接続文字列 |
Azure Storageへの接続文字列を設定します。 |
azureStorageBlobContainerName |
nuget | パッケージを保存するBlobのコンテナ名を設定します。 |
azureStorageTableName |
NuGetPackages |
パッケージの情報を保存するTableのテーブル名を設定します。 |
redirectBlobUrlWithSAS |
false または true | Trueの場合はパッケージをBlobから直接ダウンロードします。Falseの場合はWebアプリ経由でダウンロードします。 |
7. 作成したWebサイトへアクセスして以下の画面が表示されることを確認します。
8. Visual Studioのオプションを開いて、パッケージマネージャーのパッケージソースに http://< azure web siteへのURL>/nuget を指定します。
実際にNuGetで追加したソースのフィードを見てエラーが出なければ(もしくは /nugetにアクセスして空のフィードが返れば)OKです。
後はこのWebサイトを指定するだけで、通常のNuGetのパッケージ管理と同じようにパッケージの追加等が可能です。
このままだとサイト自体は誰でもアクセス可なので、お好みでBasic認証するようにしたり、An IP Address Blocking HttpModule for ASP.NET in 9 minutesを参考にIPアドレスで弾いたり許可すれば良いかと。
※apiKeyはパッケージの追加時とかに使用するのでFeedやサイトそのものの認証には使ってません。
参考までにIPアドレスで制限つけたものもGitHubにあげておきました。
これであなた専用NuGetサーバーが出来ました!便利~!
サーバーの管理とかはAzure Webサイトだから不要だし、スケールも容易です。
※WebMatrixでも利用できるようにタグつけたのはいいけど、WebMatrixで.svcをホストするのは結構難儀そうですなぁ。
まとめ
というわけで、Windows Azure Web Sitesを使うと簡単にWebアプリがホストできるよ!というネタでしたー。
今回作ったソースとかは以下に公開していますので適当にどうぞ。
オチは?
まぁなんていうか、mygetとかNuGetGalleryがAzure対応してるからこれでイイジャン!という気もする。’`,、(‘∀`) ‘`,、
ウワァァ—–。゚(゚´Д`゚)゚。—–ン!!!!
まぁNuGetGalleryはAzure Drive使ってたり個人的にはイマイチ。(フロントエンドはいいんだけど。誰か改造してください。)