View a markdown version of this page

デプロイマニフェストを使用した複数のアプリケーションと ASP.NET コアアプリケーションの実行 - AWS Elastic Beanstalk

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

デプロイマニフェストを使用した複数のアプリケーションと ASP.NET コアアプリケーションの実行

デプロイマニフェストで、Elastic Beanstalk にアプリケーションをデプロイする方法を伝えることができます。この方法を使用すると、ウェブサイトのルートパスで実行される個々の ASP.NET アプリケーション用のソースバンドルを生成するために、MSDeploy を使用する必要がなくなります。マニフェストファイルを使用することにより、異なるパスで複数のアプリケーションを実行することが可能になります。または、Elastic Beanstalk に対して、ASP.NET Core を使用してアプリケーションのデプロイと実行を行うように指示することもできます。また、デプロイマニフェストは、アプリケーションを実行するためのアプリケーションプールの設定にも使用できます。

デプロイマニフェストは、Elastic Beanstalk へ .NET Core アプリケーションのサポートを追加します。.NET Framework アプリケーションは、デプロイマニフェストなしでデプロイできます。ただし、.NET Core アプリケーションを Elastic Beanstalk で実行する場合は、デプロイマニフェストが必要です。デプロイマニフェストを使用する際には、まず各アプリケーションのサイトアーカイブを作成します。その上で、デプロイマニフェストを集録するための別の ZIP アーカイブ内に、先に作成したサイトアーカイブをバンドルします。

デプロイマニフェストを使用すると、異なるパスで複数のアプリケーションを実行することもできます。デプロイマニフェストは、多くのデプロイのターゲットを、サイトアーカイブと IIS が実行するパスにより個別に定義します。たとえば、/api パスで非同期リクエストを行うウェブ API を実行し、ルートパスでその API を実行するウェブアプリケーションを実行できます。

デプロイマニフェストを使用して、カスタムバインディングと物理パスを備えた IIS ウェブサイトを設定できます。これにより、アプリケーションをデプロイする前に、特定のポートまたはホスト名をリッスンするウェブサイトを設定できるようになります。

デプロイマニフェストは、IIS または Kestrel のアプリケーションプールを使用して、複数のアプリケーションを実行するために使用することもできます。アプリケーションプールを設定して、アプリケーションの定期的な再起動、32 ビットアプリケーションの実行、または、.NET Framework ランタイムの特定バージョンの使用ができます。

完全にカスタマイズするには、Windows PowerShell で独自のデプロイスクリプトを作成し、Elastic Beanstalk にアプリケーションのインストール、アンインストール、再起動のために実行するスクリプトを伝えます。

デプロイマニフェストと関連機能を使用するには、Windows Server プラットフォームバージョン 1.2.0 以降が必要です。

IIS リセットのスキップなど、使用可能なすべての設定オプション、プロパティ、および高度な機能の詳細については、デプロイマニフェストスキーマリファレンスを参照してください。

.NET core アプリケーション

デプロイマニフェストを使用すると、Elastic Beanstalk で .NET Core アプリケーションを実行することができます。.NET Core は .NET のクロスプラットフォームバージョンで、コマンドラインツール (dotnet) が付属しています。このマニフェストにより、アプリケーションの生成、ローカルでの実行、および公開の準備を行うことができます。

Elastic Beanstalk で .NET Core アプリケーションを実行するには、dotnet publish を実行し、その出力からディレクトリをすべて削除した内容を、ZIP アーカイブにパッケージします。サイトアーカイブを、デプロイマニフェストを使って、デプロイターゲットのタイプ aspNetCoreWeb と一緒にソースバンドルに配置します。

以下のデプロイマニフェストは、ルートパスの dotnet-core-app.zip という名前のサイトアーカイブから .NET Core アプリケーションを実行します。

例 aws-windows-deployment-manifest.json - .NET core
{ "manifestVersion": 1, "deployments": { "aspNetCoreWeb": [ { "name": "my-dotnet-core-app", "parameters": { "archive": "dotnet-core-app.zip", "iisPath": "/" } } ] } }

マニフェストとサイトアーカイブを ZIP アーカイブにバンドルし、ソースバンドルを作成します。

例 dotnet-core-bundle.zip
. |-- aws-windows-deployment-manifest.json `-- dotnet-core-app.zip

サイトアーカイブには、コンパイルされたアプリケーションコード、依存関係、web.config ファイルが含まれています。

例 dotnet-core-app.zip
. |-- Microsoft.AspNetCore.Hosting.Abstractions.dll |-- Microsoft.AspNetCore.Hosting.Server.Abstractions.dll |-- Microsoft.AspNetCore.Hosting.dll |-- Microsoft.AspNetCore.Http.Abstractions.dll |-- Microsoft.AspNetCore.Http.Extensions.dll |-- Microsoft.AspNetCore.Http.Features.dll |-- Microsoft.AspNetCore.Http.dll |-- Microsoft.AspNetCore.HttpOverrides.dll |-- Microsoft.AspNetCore.Server.IISIntegration.dll |-- Microsoft.AspNetCore.Server.Kestrel.dll |-- Microsoft.AspNetCore.WebUtilities.dll |-- Microsoft.Extensions.Configuration.Abstractions.dll |-- Microsoft.Extensions.Configuration.EnvironmentVariables.dll |-- Microsoft.Extensions.Configuration.dll |-- Microsoft.Extensions.DependencyInjection.Abstractions.dll |-- Microsoft.Extensions.DependencyInjection.dll |-- Microsoft.Extensions.FileProviders.Abstractions.dll |-- Microsoft.Extensions.FileProviders.Physical.dll |-- Microsoft.Extensions.FileSystemGlobbing.dll |-- Microsoft.Extensions.Logging.Abstractions.dll |-- Microsoft.Extensions.Logging.dll |-- Microsoft.Extensions.ObjectPool.dll |-- Microsoft.Extensions.Options.dll |-- Microsoft.Extensions.PlatformAbstractions.dll |-- Microsoft.Extensions.Primitives.dll |-- Microsoft.Net.Http.Headers.dll |-- System.Diagnostics.Contracts.dll |-- System.Net.WebSockets.dll |-- System.Text.Encodings.Web.dll |-- dotnet-core-app.deps.json |-- dotnet-core-app.dll |-- dotnet-core-app.pdb |-- dotnet-core-app.runtimeconfig.json `-- web.config

複数のアプリケーションを実行する

デプロイマニフェストを使って、複数のデプロイターゲットを指定することにより、複数のアプリケーションを実行できます。

以下のデプロイマニフェストでは 2 つの .NET Core アプリケーションを設定します。WebApiSampleApp アプリケーションは、シンプルなウェブ API を実装し、/api パスで非同期リクエストを提供します。DotNetSampleApp アプリケーションは、ルートパスでリクエストを処理するウェブアプリケーションです。

例 aws-windows-deployment-manifest.json - multiple apps
{ "manifestVersion": 1, "deployments": { "aspNetCoreWeb": [ { "name": "WebAPISample", "parameters": { "appBundle": "WebApiSampleApp.zip", "iisPath": "/api" } }, { "name": "DotNetSample", "parameters": { "appBundle": "DotNetSampleApp.zip", "iisPath": "/" } } ] } }

複数のアプリケーションのサンプルアプリケーションはこちらで入手できます:

IIS ウェブサイトを設定する

デプロイマニフェストを使用して、カスタムバインディングと物理パスを備えた IIS ウェブサイトを設定できます。これは、特定のポートでリッスンしたり、カスタムホスト名を使用したり、特定のディレクトリのコンテンツを処理したりするウェブサイトを設定する必要がある場合に役立ちます。

次のデプロイマニフェストは、特定のポート番号とカスタム物理パスを使用して HTTP をリッスンするカスタム IIS ウェブサイトを設定します。

例 aws-windows-deployment-manifest.json - IIS ウェブサイト設定
{ "manifestVersion": 1, "iisConfig": { "websites": [ { "name": "MyCustomSite", "physicalPath": "C:\inetpub\wwwroot\mysite", "bindings": [ { "protocol": "http", "port": 8080, "hostName": "mysite.local" } ] } ] }, "deployments": { "aspNetCoreWeb": [ { "name": "my-dotnet-core-app", "parameters": { "appBundle": "dotnet-core-app.zip", "iisWebSite": "MyCustomSite", "iisPath": "/" } } ] } }

この例では、以下のようになっています:

  • 「MyCustomSite」という名前のウェブサイトがカスタム物理パスで作成されます

  • ウェブサイトには、特定のホスト名を持つ HTTP バインディングがポート 8080 にあります

  • ASP.NET Core アプリケーションは、iisWebSite パラメータを使用してこのカスタムウェブサイトにデプロイされます

pplication Request Routing (ARR) を使用する

Application Request Routing (ARR) モジュールと URL Rewrite モジュールはプリインストールされており、Elastic Beanstalk Windows AMI で利用可能です。これらのモジュールにより、ebextensions またはアプリケーション設定を使用した IIS 設定を介した高度なルーティングシナリオと URL 操作が可能になります。

次の例は、カスタムポートを使用してウェブサイトを設定するシンプルなデプロイマニフェストと基本的な ARR ルーティングを設定する ebextensions 設定を組み合わせたものを示しています。

例 aws-windows-deployment-manifest.json - シンプルな ARR セットアップ
{ "manifestVersion": 1, "iisConfig": { "websites": [ { "name": "ARRSite", "physicalPath": "C:\\inetpub\\wwwroot\\arrsite", "bindings": [ { "protocol": "http", "port": 8080, "hostName": "localhost" } ] } ] }, "deployments": { "aspNetCoreWeb": [ { "name": "BackendApp", "parameters": { "appBundle": "backend-app.zip", "iisWebSite": "ARRSite", "iisPath": "/backend" } } ] } }

ARR 設定は ebextensions を介して行われます。次の設定により、基本的な ARR ルーティングルールをセットアップします。

例.ebextensions/arr-config.config - 基本的な ARR 設定
files: "C:\\temp\\configure-arr.ps1": content: | # Enable ARR proxy at server level Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/proxy' -Name 'enabled' -Value 'True' # Clear any existing global rules to avoid conflicts Clear-WebConfiguration -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/rewrite/globalRules' # Add global rule to route all requests to backend Add-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' ` -Filter 'system.webServer/rewrite/globalRules' ` -Name '.' ` -Value @{ name = 'Route_to_Backend' stopProcessing = 'True' match = @{ url = '^(?!backend/)(.*)' } action = @{ type = 'Rewrite' url = 'http://localhost:8080/backend/{R:1}' } } container_commands: 01_configure_arr: command: powershell -ExecutionPolicy Bypass -File "C:\\temp\\configure-arr.ps1" waitAfterCompletion: 0

この設定では、ポート 8080 でウェブサイトを作成し、すべての受信リクエストをそのサイトで実行されているバックエンドアプリケーションにルーティングするように ARR をセットアップします。

アプリケーションプールを設定する

Windows 環境では、複数のアプリケーションをサポートできます。そのためには、次のような 2 つのアプローチが存在します。

  • Kestrel ウェブサーバーでは、アウトプロセスホスティングモデルを使用できます。このモデルでは、複数のアプリケーションを 1 つのアプリケーションプールで実行するように構成します。

  • プロセス内ホスティングモデルを使用できます。このモデルでは、複数のアプリケーションプールを使用して、各プールに 1 つのアプリケーションのみを持つ複数のアプリケーションを実行します。IIS サーバーを使用していて、複数のアプリケーションを実行したい場合には、この方法を使用する必要があります。

1 つのアプリケーションプールで複数のアプリケーションを実行するように Kestrel を構成するには、hostingModel="OutofProcess" ファイルに web.config を追加で記述します。次に挙げるサンプルを参考にしてください。

例 web.config - Kestrel アウトプロセスホスティングモデル用
<configuration> <location path="." inheritInChildApplications="false"> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\CoreWebApp-5-0.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="OutofProcess" /> </system.webServer> </location> </configuration>
例 aws-windows-deployment-manifest.json - 複数のアプリケーション
{ "manifestVersion": 1, "deployments": {"msDeploy": [ {"name": "Web-app1", "parameters": {"archive": "site1.zip", "iisPath": "/" } }, {"name": "Web-app2", "parameters": {"archive": "site2.zip", "iisPath": "/app2" } } ] } }

IIS では、インプロセスホスティングモデルが使用されているため、1 つのアプリケーションプールでの複数のアプリケーションの実行はサポートされていません。したがって、複数のアプリケーションを構成するには、各アプリケーションを個別のアプリケーションプールに割り当てる必要があります。つまり、1 つのアプリケーションプールに割り当てられるのは、1 つのアプリケーションのみです。

aws-windows-deployment-manifest.jsonファイルで、IIS を異なるアプリケーションプールを使用するように構成できます。次のサンプルファイルを参考にしながら、同様な更新を行ってください。

  • iisConfig というサブセクションを含む、appPools というセクションを追加します。

  • appPools ブロックに、アプリケーションプールをリストします。

  • deployments セクションで、各アプリケーションの parameters セクションを定義します。

  • parameters セクションでは、各アプリケーションのアーカイブ、実行するパス、および実行するために使用する appPool を指定します。

次のデプロイマニフェストでは、10 分ごとにアプリケーションを再起動する 2 つのアプリケーションプールを構成しています。同時に、指定されたパスで実行される .NET Framework ウェブアプリケーションにも、アプリケーションをアタッチしています。

例 aws-windows-deployment-manifest.json - アプリケーションプールごとに 1 つのアプリケーション
{ "manifestVersion": 1, "iisConfig": {"appPools": [ {"name": "MyFirstPool", "recycling": {"regularTimeInterval": 10} }, {"name": "MySecondPool", "recycling": {"regularTimeInterval": 10} } ] }, "deployments": {"msDeploy": [ {"name": "Web-app1", "parameters": { "archive": "site1.zip", "iisPath": "/", "appPool": "MyFirstPool" } }, {"name": "Web-app2", "parameters": { "archive": "site2.zip", "iisPath": "/app2", "appPool": "MySecondPool" } } ] } }

カスタムデプロイを定義する

さらにきめ細かく制御するには、カスタムデプロイを定義することによって、アプリケーションのデプロイを完全にカスタマイズできます。カスタムデプロイでは、Elastic Beanstalk は指定した PowerShell スクリプトのみを実行し、ユーザーに代わって IIS 管理は実行しません。これは、インストール前に Elastic Beanstalk が自動的に IIS を停止msDeployし、その後起動して、必要に応じて再起動する および aspNetCoreWebデプロイとは異なります。カスタムデプロイの場合、スクリプトはアプリケーションコンテンツを配置し、環境 (IIS など) を設定し、アプリケーションを再起動します。

重要

ロードバランシングされたウェブサーバー環境では、Elastic Beanstalk は、ポート 80 で環境のヘルスチェックパス (/デフォルトでは) をリクエストして、インスタンスのヘルスをチェックします。何かがそのパスを処理する必要があります。そうしないと、すべてのデプロイスクリプトが成功しても環境が異常になります。これは、カスタムデプロイの一般的な原因であり、エラーなしで完了しますが、環境は赤色の状態のままになります。スタンドアロンのカスタムデプロイの場合は、デフォルトウェブサイトのルートからアプリケーションを提供します。複数のアプリケーションマニフェストなど、別のデプロイがすでにヘルスチェックパスを提供している場合、カスタムアプリケーションをサブパスに配置するのは有効です。環境の状態の詳細については、「環境のモニタリング」を参照してください。

カスタムデプロイでは、最大 3 つのスクリプトを定義します。次の表は、各スクリプト、Elastic Beanstalk がスクリプトを実行するタイミング、およびスクリプトが何をする必要があるかを示しています。

スクリプト Elastic Beanstalk が実行する場合 責任
uninstall 新しいアプリケーションバージョンをインストールする前、つまり各アプリケーションのデプロイ前。 サービスを停止するか、以前のバージョンのファイルを削除します。
install 各アプリケーションのデプロイ中。 ファイルをデプロイし、IIS またはサービスを設定し、ヘルスチェックパスでアプリケーションを提供します。
restart アプリケーションのデプロイ後および設定変更後。skipIISReset を に設定するとtrue、Elastic Beanstalk はアプリケーションのデプロイでこのスクリプトをスキップしますが、設定の変更でも実行します。Restart App Server を選択すると、プラットフォームレベルが実行されiisreset、カスタム再起動スクリプトは呼び出されません。 IIS (iisreset) またはサービスを再起動して、新しいバージョンがライブになるようにします。

これらのスクリプトは、最初の環境の作成時や Auto Scaling がインスタンスを追加する (スケールアウト) など、Elastic Beanstalk がアプリケーションを新しく起動したインスタンスにデプロイするたびにも実行されます。これは、新しいインスタンスが起動時にアプリケーションをインストールするためです。

次のデプロイマニフェストは、32 ビットモードで PowerShell スクリプトを実行するように Elastic Beanstalk に指示します。install スクリプト (install.ps1)、restartスクリプト ()、スクリプト uninstall (restart.ps1) を指定しますuninstall.ps1。uninstall スクリプトは ignoreErrorsを に設定するtrueため、最初のデプロイは、削除するものがない場合でも失敗しません。

例 aws-windows-deployment-manifest.json - custom deployment
{ "manifestVersion": 1, "deployments": { "custom": [ { "name": "Custom site", "architecture": 32, "scripts": { "install": { "file": "install.ps1" }, "restart": { "file": "restart.ps1" }, "uninstall": { "file": "uninstall.ps1", "ignoreErrors": true } } } ] } }

ソースバンドルには、マニフェスト、スクリプトと一緒にアプリケーションの実行に必要なアーティファクトをすべて含めます。Elastic Beanstalk は、カスタムデプロイ用にこれらのアーティファクトを抽出しません。スクリプトはそれらを抽出する必要があります。次の例では、アプリケーションコンテンツは としてパッケージ化されていますMyApp.zip。

例 Custom-site-bundle.zip
. |-- aws-windows-deployment-manifest.json |-- install.ps1 |-- restart.ps1 |-- uninstall.ps1 `-- MyApp.zip

次のスクリプトは、IIS がホストするアプリケーションの完全なhealth-check-correctカスタムデプロイを示しています。install.ps1 スクリプトはアプリケーションコンテンツを抽出し、デフォルトウェブサイトの物理パスをポイントします。これにより、アプリケーションはヘルスチェックが検索されるルートパス (/) から提供されます。

例 install.ps1
$ErrorActionPreference = "Stop" $appPath = "C:\inetpub\MyApp" if (Test-Path $appPath) { Remove-Item $appPath -Recurse -Force } # Elastic Beanstalk doesn't extract your bundle for custom deployments, so extract it yourself. # MyApp.zip ships in the bundle, alongside this script. Resolve it relative to the script's # own location so the path is reliable regardless of the current working directory. $scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { (Get-Location).Path } $bundleZip = Join-Path $scriptDir "MyApp.zip" Add-Type -AssemblyName "System.IO.Compression.FileSystem" [IO.Compression.ZipFile]::ExtractToDirectory($bundleZip, $appPath) # Serve from the Default Web Site root ("/"), where the health check looks. Import-Module WebAdministration Set-ItemProperty "IIS:\Sites\Default Web Site" -Name physicalPath -Value $appPath iisreset.exe /restart if ($LASTEXITCODE -ne 0) { exit 1 }
例 restart.ps1
$ErrorActionPreference = "Stop" iisreset.exe /restart if ($LASTEXITCODE -ne 0) { exit 1 }
例 uninstall.ps1
# Stop IIS first. While the site is live, w3wp holds locks on files under the app directory, # which would make the following removal fail. iisreset.exe /stop | Out-Null Remove-Item "C:\inetpub\MyApp" -Recurse -Force -ErrorAction SilentlyContinue

カスタムデプロイスクリプトを作成するときは、次の点に注意してください。

  • ヘルスチェックパスを提供します。デフォルトのウェブサイトの物理パスをアプリケーションにポイントするか、ヘルスチェックパスにデプロイして、ヘルスチェックが成功するようにします。

  • デフォルトのドキュメントを含めます。サイトルートにデフォルトドキュメントがない場合、 は HTTP 403 GET /を返し、ヘルスチェックは失敗します。<defaultDocument> 要素を設定するweb.configファイルを出荷するか、 Default.htm や などの IIS デフォルトドキュメント名と一致するようにランディングページに名前を付けますindex.htm。

  • IIS を自分で再起動します。Elastic Beanstalk はカスタムデプロイに対して IIS 管理を実行しないため、変更を有効にするiisresetにはスクリプトを実行する必要があります。

  • スクリプトに関連するバンドルされたファイルを見つけます。Elastic Beanstalk は、スクリプトとバンドルされたアーティファクトを同じディレクトリに抽出します。特定の現在の作業ディレクトリを引き受けるのではなく、バンドルされたファイルを $PSScriptRoot (実行中のスクリプトを含むフォルダ) で解決します。

  • 失敗はデプロイに失敗します。外部コマンドの$LASTEXITCODE後に を設定$ErrorActionPreference = "Stop"して確認します。そうしないと、壊れたスクリプトが正常に終了し、アプリケーションが正しく実行されていなくても、Elastic Beanstalk はデプロイを成功として扱います。

例: セルフホスト型の Windows サービス

カスタムデプロイでは、IIS がホストするサイトの代わりに Windows サービスを実行できます。Elastic Beanstalk Windows プラットフォームは、ワーカー環境層をサポートしていません。負荷分散された環境では、ロードバランサーはポート 80 のヘルスチェックパスをチェックするため、Windows サービスは環境を正常に保つためにそのリクエストに応答する必要があります。次の例は、ポート 80 自体をリッスンするセルフホスト型サービスであるため、コンパニオン IIS サイトは必要ありません。

注記

Windows プラットフォームにはワーカー階層がないため、バックグラウンドのみのサービスは負荷分散された環境でヘルスチェックに応答する必要があります。サービスがヘルスチェックパスにも応答するか (ここを参照)、それを提供するサイトと一緒にバックグラウンド作業を実行します。

マニフェストは、サービスの構築に使用される 64 ビット C# コンパイラと一致する 64 ビットモードでスクリプトを実行します。

例 aws-windows-deployment-manifest.json - Windows サービス
{ "manifestVersion": 1, "deployments": { "custom": [ { "name": "EbCustomService", "architecture": 64, "scripts": { "install": { "file": "serviceInstall.ps1" }, "restart": { "file": "serviceRestart.ps1" }, "uninstall": { "file": "serviceUninstall.ps1", "ignoreErrors": true } } } ] } }

バンドルには、マニフェスト、3 つのスクリプト、サービスソースコード、version.txtおよび ファイル (コンテンツはバージョン文字列 など) が付属していますv1。インストールスクリプトはインスタンスでサービスをコンパイルするため、バンドルにビルドツールチェーンは必要ありません。

例 Custom-service-bundle.zip
. |-- aws-windows-deployment-manifest.json |-- EbCustomService.cs |-- serviceInstall.ps1 |-- serviceRestart.ps1 |-- serviceUninstall.ps1 `-- version.txt

このserviceInstall.ps1スクリプトは IIS からポート 80 を解放し、バンドルされたソースからインボックス C# コンパイラ (csc.exe) を使用してサービスをコンパイルし、LocalSystemサービスとして登録して起動します。として実行するとLocalSystem、URL ACL 予約http://+:80/なしでサービスがバインドされるため、例は最小限に抑えられます。本番環境では、 などの最小特権アカウントを優先NetworkServiceし、 を使用してバインディングを明示的に付与しますnetsh http add urlacl。

例 serviceInstall.ps1
# INSTALL: compile and register a self-hosted HTTP service that owns port 80. $ErrorActionPreference = "Stop" $svcName = "EbCustomService" $appPath = "C:\CustomService" $scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { (Get-Location).Path } # Free port 80 from IIS and keep it from reclaiming the port on reboot. Stop-Service W3SVC -Force -ErrorAction SilentlyContinue Set-Service W3SVC -StartupType Manual -ErrorAction SilentlyContinue # Fresh application directory. if (Test-Path $appPath) { Remove-Item $appPath -Recurse -Force } New-Item -ItemType Directory -Path $appPath | Out-Null # Compile the service with the in-box .NET Framework compiler (no build tooling needed). $csc = Join-Path $env:WINDIR "Microsoft.NET\Framework64\v4.0.30319\csc.exe" $src = Join-Path $scriptDir "EbCustomService.cs" $exe = Join-Path $appPath "EbCustomService.exe" & $csc /nologo /target:exe /out:"$exe" /reference:System.ServiceProcess.dll "$src" if ($LASTEXITCODE -ne 0) { exit 1 } # Write the content served at "/". A real service would serve its own responses; # here the install script writes a simple marker so the health check passes. $version = (Get-Content (Join-Path $scriptDir "version.txt") -Raw).Trim() Set-Content -Path (Join-Path $appPath "marker.txt") ` -Value "Custom service deployment $version succeeded" -NoNewline # Register as a LocalSystem service so it can bind http://+:80/ without a URL ACL. if (Get-Service $svcName -ErrorAction SilentlyContinue) { Stop-Service $svcName -Force -ErrorAction SilentlyContinue sc.exe delete $svcName | Out-Null # sc.exe delete is async; poll until gone so New-Service below doesn't hit # "service marked for deletion". $deadline = (Get-Date).AddSeconds(30) while ((Get-Service $svcName -ErrorAction SilentlyContinue) -and (Get-Date) -lt $deadline) { Start-Sleep -Milliseconds 500 } } New-Service -Name $svcName -BinaryPathName "`"$exe`"" ` -DisplayName "EB Custom Service" -StartupType Automatic | Out-Null Start-Service $svcName

serviceRestart.ps1 スクリプトは、新しいバージョンがライブになるようにサービスを再起動します。

例 serviceRestart.ps1
# RESTART: restart the service so the new version becomes live. $ErrorActionPreference = "Stop" $svcName = "EbCustomService" Restart-Service $svcName -Force

serviceUninstall.ps1 スクリプトはサービスを停止および削除し、以前のバージョンのファイルを削除します。最初のデプロイignoreErrorsには削除する以前のバージョンがないため、このスクリプトtrueのマニフェストは に設定されます。

例 serviceUninstall.ps1
# UNINSTALL: stop and remove the previous version before the new install. # The manifest sets ignoreErrors:true because the first deploy has nothing to remove. $ErrorActionPreference = "Stop" $svcName = "EbCustomService" $appPath = "C:\CustomService" if (Get-Service $svcName -ErrorAction SilentlyContinue) { Stop-Service $svcName -Force -ErrorAction SilentlyContinue sc.exe delete $svcName | Out-Null # sc.exe delete is async; poll until the service is really gone so the next # deploy's New-Service doesn't hit "service marked for deletion". $deadline = (Get-Date).AddSeconds(30) while ((Get-Service $svcName -ErrorAction SilentlyContinue) -and (Get-Date) -lt $deadline) { Start-Sleep -Milliseconds 500 } } if (Test-Path $appPath) { Remove-Item $appPath -Recurse -Force -ErrorAction SilentlyContinue }

サービス自体は、 HttpListenerで をホストhttp://+:80/しGET /、ロードバランサーのヘルスチェックを満たす のテキストレスポンスを返す小さな C# プログラムです。

例 EbCustomService.cs
// Minimal self-hosted HTTP Windows service. Hosts an HttpListener on http://+:80/ // and answers the load balancer's GET "/" health check with the content that the // install script wrote to marker.txt. using System; using System.IO; using System.Net; using System.ServiceProcess; using System.Text; using System.Threading; namespace EbCustomService { public class MarkerService : ServiceBase { private const string Root = @"C:\CustomService"; private HttpListener _listener; private Thread _worker; private volatile bool _running; public MarkerService() { this.ServiceName = "EbCustomService"; } protected override void OnStart(string[] args) { _running = true; _listener = new HttpListener(); _listener.Prefixes.Add("http://+:80/"); _listener.Start(); _worker = new Thread(Loop) { IsBackground = true }; _worker.Start(); } protected override void OnStop() { _running = false; try { if (_listener != null) _listener.Stop(); } catch { } } private void Loop() { while (_running) { HttpListenerContext ctx; try { ctx = _listener.GetContext(); } catch { break; } try { byte[] buf = Encoding.UTF8.GetBytes(ReadFile(Path.Combine(Root, "marker.txt"))); ctx.Response.StatusCode = 200; ctx.Response.ContentType = "text/plain"; ctx.Response.ContentLength64 = buf.Length; ctx.Response.OutputStream.Write(buf, 0, buf.Length); ctx.Response.OutputStream.Close(); } catch { } } } private static string ReadFile(string p) { try { return File.Exists(p) ? File.ReadAllText(p) : ""; } catch { return ""; } } public static void Main() { ServiceBase.Run(new MarkerService()); } } }
注記

この例では、 で提供されるレスポンス/は、アプリケーションの実際のコンテンツを表す小さなテキストマーカー (marker.txt) です。本番稼働用サービスは、代わりに独自のレスポンスを提供します。これらのスクリプトの他のすべては、作業中の Windows サービスのカスタムデプロイに最低限必要です。