Google Cloud Platform

ASP.NET Core アプリを GCP にデプロイする 4 つの方法

過去数か月にわたり、多くの .NET デベロッパーが .NET Core アプリケーションを App Engine flexible environment で稼働させるテストを行ってきました。私たち Google は、そこから得られた数々のすばらしいフィードバックに感謝するとともに、Container Engine と同様に App Engine flexible environment での .NET Core サポートについても、先ごろ正式にリリース(GA)しました。

今回サポート対象となるのは、Google Cloud Platform(GCP)での実行に最適化され、Google がサポートする Docker イメージを使用する .NET Core 1.0、1.1、2.0 です。

.NET Core アプリケーションの実行が GCP で正式にサポートされるようになった今、GCP に .NET Core アプリケーションを導入する最善の方法は何かという疑問がわいてくることでしょう。簡単に言うと、ASP.NET Core アプリケーションを GCP にデプロイする基本的な方法は 4 つあり、どれが適切かはターゲット環境に応じて決まります。

  1. Cloud Tools for Visual Studio エクステンションを利用して Visual Studio から直接デプロイする
  2. “dotnet publish” によって Framework Dependent Deployment バンドルをデプロイする
  3. カスタム Dockerfile で App Engine flexible environment にデプロイする
  4. カスタム Dockerfile で Container Engine にデプロイする
GCP にアプリケーションを導入し実行するにあたっては、1 の方法が最も簡単かつ直接的であることは言うまでもありません。1 の方法では、Dockerfile を含めすべての必要なコンポーネントの作成が水面下で行われます。

一方、2、3、4 は Visual Studio を利用できない場合に適切な方法で、コマンドラインから直接実行できます。この 3 つの方法では、アプリケーションのデプロイに必要なコンポーネントを収集して作成する必要があるほか、以下も必要です。

  • デプロイを定義し、実行に必要な依存関係がすべて含まれる .dll(アプリケーションのパブリッシュで生成)などのビルド アーティファクト
  • App Engine の場合は、アプリケーションのデプロイメント ファイルのルートにある app.yaml ファイル
アプリケーションのデプロイには Docker イメージの作成も必要です。また、Docker イメージをどのように作るかを記述した Dockerfile も用意しなければなりません。

App Engine の場合は、アプリケーションをデプロイするときに Dockerfile を作成してくれます(後述の「方法 3 : カスタム Dockerfile で App Engine にデプロイする」を参照)。一方、Container Engine にデプロイする場合は Dockerfile を自分で作成する必要があります。

4 つの方法を詳しく見ていきましょう。

方法 1 : Visual Studio から直接デプロイする

Google の Cloud Tools for Visual Studio を使用すれば、ASP.NET Core アプリケーションを GCP に直接デプロイできます。Visual Studio IDE 内からアプリケーションをデプロイする場合に必要なことは、すべてこのツールが処理してくれます。

image-0808.png

方法 2 : Framework Dependent Deployment バンドルをデプロイする

コマンドラインからアプリケーションをデプロイするときにいちばん簡単な方法は、“dotnet publish” の実行結果をデプロイして Framework Dependent Deployment バンドルを作成することです。このディレクトリには、アプリケーションの dll や、プロジェクト ファイルで参照されるすべての依存関係が含まれています。

このディレクトリを App Engine flexible environment にデプロイするには、app.yaml をビルド アーティファクト ディレクトリに配置する必要があります。これを自動的に行うには、app.yaml ファイルをソリューションのスタートアップ プロジェクトのルートで .csproj ファイルの横に置き、アウトプットにコピーされるファイルとして app.yaml を .csproj に追加します。これは、.csproj に次のコードを追加することで行います。

  <ItemGroup>
  <None Include="app.yaml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

App Engine flexible environment にデプロイするにあたって必要な最低限の app.yaml ファイルの内容は次のとおりです。

  runtime: aspnetcore
env: flex

この app.yaml は、ASP.NET Core アプリケーションのランタイムに “aspnetcore” を使っており、App Engine flexible environment の環境で実行することを示しています。追加で app.yaml の設定を行えば、より詳細にアプリケーションをカスタマイズすることも可能です。

.csproj に上記の変更を加え、“dotnet publish” コマンドでアプリケーションをパブリッシュすると、app.yaml がアウトプット ディレクトリにコピーされます。つまり、デプロイの準備が完了したディレクトリが作成されるわけです。

このディレクトリを App Engine flexible environment にデプロイするには、以下の手順に従います。

  1. スタートアップ プロジェクトのディレクトリから、お好みの設定で “dotnet publish” コマンドを実行します。以下に例を示します。
    dotnet publish -c Release
    これで、“bin\\netcore\publish” というディレクトリにリリース ビルドがパブリッシュされます。アプリケーションのデプロイメント ファイルや、.csproj に app.yaml を追加していた場合はそれも含まれます。

bG9Nyx4V6-CaRUeo-Jl72WaftvieFvNXet_hs2P11WkxJA_W0IqHTjyt0MXOqKrY3xulnmm0yoQkIBJHhME5FPwJQChgYdBVcCEP7apLydylWqVljqFnEaita0_GbLb3Z1FTTrMe9khr.PNG

  1. 以下のコードを実行して App Engine flexible environment にデプロイします。
    gcloud app deploy bin\<configuration>\netcore<version>\publish\app.yaml
    アプリケーションが App Engine にデプロイされ、アプリケーションを Docker イメージにラップするといった複雑な作業はすべて gcloud が処理してくれます。

LuMBCkTnd9Kv6b-2QEz9bOFWbUaf3kejX8miCKRyfNq2yWOSkxm6aNZzm0yOWk2QTFN6GDS2lsm9nypcxNYPPugEGk-dp_pX55ieEQZ1MDWRJkdFAWaFuw9KhqJTVE2GG1CTWwwGhsk4.PNG

方法 3 : カスタム Dockerfile で App Engine にデプロイする

アプリケーションのコンテナのビルド方法をより細かく制御したいときは、独自の Dockerfile を指定します。カスタム パッケージをコンテナにインストールする必要があったり、追加のツールが必要だったりする場合や、コンテナのコンテンツをさらに制御する必要がある場合は、この方法でやってみましょう。

この場合に必要なのは次の app.yaml です。

  runtime: custom
env: flex

“runtime: custom” という記述は、アプリケーション イメージのビルドに必要な Dockerfile が別途 App Engine に提供されることを意味しています。

次に、アプリケーション用の Dockerfile を作成します。Dockerfile の作成方法には次の 2 つがあります。

  1. パブリッシュされたアプリケーション用に Dockerfile を作成する
    パブリッシュされたアプリケーションのルートに沿ってこのまま進みたい場合は、Dockerfile を指定し、パブリッシュされたディレクトリをベースにアプリケーションのイメージをビルドします。Dockerfile は次のようになります。
    FROM gcr.io/google-appengine/aspnetcore:2.0 ADD ./ /app ENV ASPNETCORE_URLS=http://*:${PORT} WORKDIR /app ENTRYPOINT [ "dotnet", "MainProject.dll" ]
    この Dockerfile の例では、ベース イメージとして “gcr.io/google-appengine/aspnetcore:2.0” が使われていることに注目してください。ここでは、App Engine と Container Engine での ASP.NET Core アプリケーションの実行に最適化された Docker イメージを作成しましたが、カスタム Dockerfile にはこのイメージを使用することを強くお勧めします。
    Googleでも、デプロイにあたって Dockerfile を生成するときは、このイメージと同じものを使っています。ただし、アプリケーションの .NET Core ランタイムの正しいバージョンを参照するように変更することを忘れないでください。
    パブリッシュされたディレクトリに Dockerfile があることを確認するには、.csproj に Dockerfile を追加してください。そうすれば、アプリケーションがパブリッシュされた際に Dockerfile もパブリッシュされます。Dockerfile がスタートアップ プロジェクトのルート、つまり .csproj および app.yaml と同じレベルにあると想定し、次のコードを .csproj に追加します。
    <ItemGroup> <None Include="app.yaml" CopyToOutputDirectory="PreserveNewest" /> <None Include="Dockerfile" CopyToOutputDirectory="PreserveNewest" /> </ItemGroup>
    この変更により、“dotnet publish” を実行するたびに、パブリッシュされたディレクトリに両ファイルがコピーされるようになります。デプロイするには、上述の手順に従ってください。
    dotnet publish -c Release

Guhtsf70N25yyMwlr7Yy9unD9AAbUdQSNPo7tUUDDdexo_iUN3M5cNHKyF37AEZYOUgB82JNDx7g0Icez05aK1jIacG6SATKQmC5dt9pUPE53XMsNMbG1RFAS843DxGiKEJocgYI4mfe.PNG

gcloud app deploy bin\<configuration>\netcore<version>\publish\app.yaml

image-0809.png

  1. アプリケーションのコンパイルとパブリッシュを行う Dockerfile を作成する
    Linux 上での ASP.NET Core アプリケーションのビルドが可能な場合は、マルチステージ Dockerfile を使うことも検討すべきです。これは、最終的なアプリケーションのイメージをビルドする前に、ビルド プロセス中にリストアとパブリッシュを実行するものです。こうすればデプロイ中にビルドが終わるため、アプリケーションのデプロイがより便利になります。
    この場合の Dockerfile は次のとおりです。
    # First let’s build the app and publish it. FROM gcr.io/cloud-builders/csharp/dotnet AS builder COPY . /src WORKDIR /src RUN dotnet restore --packages /packages RUN dotnet publish -c Release -o /published # Now let's build the app's image. FROM gcr.io/google-appengine/aspnetcore:2.0 COPY --from=builder /published /app ENV ASPNETCORE_URLS=http://*:${PORT} WORKDIR /app ENTRYPOINT [ "dotnet", "multistage-2.0.dll" ]
    この Dockerfile では、“gcr.io/cloud-builders/csharp/dotnet” というビルダ イメージを利用しています。このイメージは、サポート対象となる .NET Core 全バージョンの .NET SDK をラップするものです。
    この手法の主なメリットは、app.yaml と Dockerfile をプロジェクトのルートで .csproj の横に置くことができる点です。そのため、アプリケーションをデプロイするには次のコマンドを実行するだけで済みます。
    gcloud app deploy app.yaml

Ca08bmLgc7s1OTFKvrXwdmAcYQFZN5QUfmZQODM2Hdupu-1AXd_niBklcl5r-KodNZ1z_ubQ3OrowOZsg26murXAIknEJCpNQHQ8aWLjwU5wnQbKnAPm5klujmLzFwMGKSwf7fCOp532.PNG

これにより、アプリケーションのソースが Cloud Container Builder にアップロードされ、そこでビルドが行われます。結果として得られるビルド アーティファクトは最終的なアプリケーションのイメージを生成するときに使われ、そのイメージは App Engine にデプロイされます。ビルド プロセス中にテストも実行できるので、これを完全な CI/CD(継続的インテグレーション / 継続的デリバリ)ソリューションとすることができます。

方法 4 : Container Engine にデプロイする

ワークロードを細かく制御したり、App Engine でサポートされていないプロトコルを使用したりする必要がある場合は、Container Engine を利用しましょう。Container Engine へのデプロイは、App Engine へのデプロイと少し似ています。アプリケーションの Docker イメージを作成し、それを既存のクラスタにデプロイするからです。

アプリケーションの Docker イメージを作成するには、上記の方法 3 で説明した方法をとります。すなわち、パブリッシュされたアプリケーション用の Dockerfile、もしくは Docker ビルド プロセス中にアプリケーションをビルドしてパブリッシュする Dockerfile のいずれかを使用します。

アプリケーションの Docker イメージを作成する

アプリケーション用の Dockerfile を記述するときは上記で説明したどの方法を使ってもいいのですが、Container Engine にデプロイしたい場合は Docker イメージを自分で作成する必要があります。

また、イメージをリポジトリにプッシュする必要もあります。そのリポジトリから Container Engine がイメージを読み取るからです。いちばん簡単なのは、イメージを Cloud Container Registry にプッシュすることです。Cloud Container Registry はプライベートな Docker イメージのリポジトリであり、Cloud Storage にプロジェクト用のイメージを保管します。

Docker イメージを作成して Container Registry にプッシュする最も簡単な方法は、Cloud Container Builder を使うことです。これは、操作ひとつで Docker イメージを作成して Container Registry にプッシュするホスト型の Docker サービスです。

まず、アプリケーションのルート デプロイメント ディレクトリに移動しましょう。このディレクトリは、選んだオプションによって “dotnet publish” の際に作成されたか、プロジェクトのルートとなっているはずです。そして次のコマンドを実行します。

  kubectl run myservice --image=gcr.io/<your project id>/<app name> --port=8080

このコマンドにより、“gcr.io/$PROJECT_ID/” という Docker イメージが作成されます。“$PROJECT_ID” は自動的に GCP プロジェクトの ID に置き換えられ、“” にはアプリケーションの名称が入ります。

Container Engine クラスタにイメージをデプロイする

次に、作成したイメージを Container Engine にデプロイします。ただし、その前にまず、Container Engine とのやり取りに使用する kubectl をインストールしなくてはなりません。kubectl を使えば、Container Engine クラスタとのやり取りをコマンドラインで行えるようになります。

kubectl をインストールする最も簡単な方法は、以下の gcloud コマンドを実行することです。

  gcloud components install kubectl

クラスタのクレデンシャルもマシンに保存し、kubectl がアクセスできるようにしておきましょう。Container Engine クラスタを作成したら、次のコマンドを実行してクレデンシャルを入手します。

  gcloud container clusters get-credentials

それでは、Container Engine にアプリケーションをデプロイする方法を見ていきましょう。まずイメージを実行するデプロイメントを作成します。次のコマンドを使えば簡単です。

  kubectl run myservice --image=gcr.io/<your project id>/<app name> --port=8080

これで、アプリケーション実行のための新しい Kubernetes デプロイメントと、必要なポッドがすべて作成されます。また、--replicas=n のパラメータを使って実行コードのレプリカの番号を指定することも可能です。n には好きな番号を入れてください。

注 : ここでは、Docker コンテナがポート 8080 をエクスポートすることを前提としています。これは App Engine flexible environment のデフォルトです。また、ポート 80 からサービスを公開することも前提としています。こうしたデフォルト設定を変更したい場合は、こちらのドキュメントを参考してください。

次に、Kubernetes デプロイメントを公開し、クラスタ外からも見えるようにしてください。いちばん簡単な方法は次のコマンドを使うことです。

  kubectl expose deployment myservice --port=80 --target-port=8080 
--type=LoadBalancer

これにより、上記で作成したデプロイメントが LoadBalancer タイプのサービスで公開されます。つまり、これはパブリック IP アドレスを持つパブリック サービスであることを示しています。

最後に

私たちは、.NET デベロッパーに GCP を提供できることを大変うれしく思っています。App Engine flexible environment のことが好きか、あるいは Container Engine のパワーに魅力を感じているかに関係なく、私たちはすべての .NET デベロッパーをサポートします。

また、.NET デベロッパーの生産性を高めるための投資も行っています。GCP 上での .NET アプリケーションの構築方法については、こちらを参照してください。.NET 関連のドキュメントが用意されています。

私たちはオープンソースに全力を注いでいます。ASP.NET Core アプリケーションの Docker イメージはこちらのリポジトリにあります。フィードバックも受け付けていますので、アイデアや提案がありましたら同リポジトリまで自由にお寄せください。

* この投稿は米国時間 10 月 11 日、C# Team Lead である Ivan Naranjo によって投稿されたもの(投稿はこちら)の抄訳です。

- By Ivan Naranjo, C# Team Lead