この記事の概要
C#でCloud Runを動かしてみました。
基本は公式ガイド通りでしたが、説明が不十分だったり、自分がポカしたとこもあったので、備忘録もかねて簡単にまとめてみます。
環境
ローカルマシン
windows10 pro
公式の手順(2021.05.29時点)ざっくり
手順変わるかもしれないので、一応現時点のものをざっくり記しておきますが、公式のほうが詳しいので公式を見た方がよいです。
事前準備
GCPのプロジェクトセレクタページで、Google Cloud プロジェクトを作っておく。
Cloud プロジェクトに対して課金が有効になっていることを確認
Cloud SDKのインストール
自分はdockerではなく、windowsに直接入れました
アプリの作成
適当なディレクトリで、サンプルのwebプロジェクトを作成する
dotnet new web -o helloworld-csharp
以下の内容に書き換える
Program.cs
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace helloworld_csharp
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
string port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
string url = String.Concat("http://0.0.0.0:", port);
return Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>().UseUrls(url);
});
}
}
}
Startup.cs
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace helloworld_csharp
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
var target = Environment.GetEnvironmentVariable("TARGET") ?? "World";
await context.Response.WriteAsync($"Hello {target}!\n");
});
});
}
}
}
Container Registryにアップロード
Dockerfileをルートに作成
Dockerfile
# Use Microsoft's official build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
WORKDIR /app
# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore
# Copy local code to the container image.
COPY . ./
WORKDIR /app
# Build a release artifact.
RUN dotnet publish -c Release -o out
# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS runtime
WORKDIR /app
COPY --from=build /app/out ./
# Run the web service on container startup.
ENTRYPOINT ["dotnet", "helloworld-csharp.dll"]
gcloud用のignoreファイルである.gcloudignoreファイルを作成
# The .gcloudignore file excludes file from upload to Cloud Build.
# If this file is deleted, gcloud will default to .gitignore.
#
# https://cloud.google.com/cloud-build/docs/speeding-up-builds#gcloudignore
# https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore
**/obj/
**/bin/
# Exclude git history and configuration.
.git/
.gitignore
.dockerignoreファイルを、.gcloudignore と同じ内容で作成
ビルドとデプロイ
ビルド
gcloud builds submit --tag gcr.io/PROJECT-ID/helloworld
デプロイ
gcloud run deploy --image gcr.io/PROJECT-ID/helloworld --platform managed
ハマったところ
gcloud build submit が成功しない1
xxxxxx@cloudbuild.gserviceaccount.com does not have storage.objects.get access と言われて失敗します。これはCloud Buildのほうのドキュメントで触れられていますが、Cloud Storage に書きこむための権限が必要です。service account permissonの一覧には出てないので、IAM sectionのところから、CloudBuildのサービスアカウント(xxxx@cloudbuild.gserviceaccount.com)に、Storage オブジェクト作成者のロールを付与してやる必要があります。
gcloud build submit が成功しない2
これはただの僕のポカなのですが、gcloud buildを実行しているディレクトリがアプリルートではありませんでした。こんなミスやるのは僕以外にいないと思いますがご注意ください。この際は、unable to prepare context: unable to evaluate symlinks in Dockerfile path のようなエラーログが出ます。当たり前ですね。
gcloud build submit が成功しない3
The reference assemblies for .NETFramework,Version=v5.0 were not found.と言われました。は?となりましたが、どうやらdotnet new コマンドで作成したプロジェクトはデフォルトでは.NET 5になるらしく、DockerfileのFROMで指定しているイメージとは異なってしまい、失敗しているようでした。
.csprojを書き換えて対応しました。
<TargetFramework>netcoreapp3.1</TargetFramework>
デプロイ後に、ページにアクセスすると403になる
こうなった人は
Allow unauthenticated invocations to [helloworld] (y/N)?
になぜかnを答えた人です。
はい、helloworldに認証もくそもないので、これはyを答えておきましょう。
終わりに
最近のクラウドにあまり触れてなかったですが、かなりすごいですね。
楽しい。
↧