はじめに
今回はterraformを利用してCloudRunを構築しminimal API(ASP.NET Core + .NET 8)
で構築したWebサーバーをデプロイする方法を紹介したいと思います。
具体的には以下の操作をしていきます。
- terraformによるCloud Run構築
- ASP.NET Coreによるプロジェクト作成
- 作成したプロジェクトを実行するDockerfileを作成
- Artifact RegistoryにDocker Imageをアップロード
Cloud Runの構築
以下のresource
を作成します。
google_cloud_run_v2_service
: Cloud Runを構築google_iam_policy
: プロジェクトのIAMポリシーを設定google_cloud_run_v2_service_iam_policy
: IAMポリシーをCloud Runに設定
↓ main.tf
# Cloud Run構築 resource "google_cloud_run_v2_service" "default" { name = "sample" location = "asia-northeast1" ingress = "INGRESS_TRAFFIC_ALL" template { containers { image = "us-docker.pkg.dev/cloudrun/container/hello" } } } # 外部からアクセスするようにIAM Policy設定 # allUsers(全てのユーザー)にroles/run.invoker(サービスとジョブの呼び出し、ジョブ実行のキャンセルが可能)を付与する data "google_iam_policy" "noauth" { binding { role = "roles/run.invoker" members = ["allUsers"] } } # IAMポリシーをCloud Runに適応する resource "google_cloud_run_v2_service_iam_policy" "policy" { location = "asia-northeast1" name = google_cloud_run_v2_service.default.name policy_data = data.google_iam_policy.noauth.policy_data }
IAM を使用したアクセス制御 | Cloud Run Documentation | Google Cloud
Cloud RunにアクセスできるURIを出力する
このコードは必須ではないですが、デプロイしたCloud RunにアクセスできるURIを出力させてあげると便利です。
↓outputs.tf
output "service_url" { value = google_cloud_run_v2_service.default.uri description = "The URL on which the deployed service is available" }
$ terraform apply ... Outputs: service_url = "https://-----.run.app"
その他のterraformコード
上記コードが大切な箇所ですが、それ以外に作成した.tf
も貼っておきます。
↓provider.tf
terraform { required_providers { google = { source = "hashicorp/google" version = "6.2.0" } } } provider "google" { project = var.project_id region = "asia-northeast1" }
↓ variables.tf
variable "project_id" { description = "GCP Project ID" }
全てのファイル構成は以下になります。
. ├── main.tf ├── outputs.tf ├── provider.tf └── variables.tf
サイトを確認する
terraform
を実行して、出力されたURIを開くと以下が表示されればOKです。
$ terraform init $ terraform apply
.NETのウェブサーバーを作成する
先程はus-docker.pkg.dev/cloudrun/container/hello
というArtifact Registory
に挙げられているサンプル用のImageを利用していましたが、これを自身で作成したものに差し替えます。
まずは.NET
でプロジェクトを作成する必要があります。やり方の詳細は以下の記事に書きました。
www.hanachiru-blog.com
# ASP.NET Core + .NET 8のプロジェクトを作成する $ dotnet new web -o CloudRunSample -f net8.0
↓ Program.cs
var builder = WebApplication.CreateBuilder(args); // PORT という環境変数が設定されていればそれを利用し、されていなければ 8080 をポートに利用する var port = Environment.GetEnvironmentVariable("PORT") ?? "8080"; // 0.0.0.0 にする理由 : https://zenn.dev/shake_sanma/articles/1c6475ba73da48 var url = $"http://0.0.0.0:{port}"; var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run(url);
Dockerfile
の作成
Mac M1では--platform linux/amd64
を指定してビルドしないといけないのですが、その対応でBUILDPLATFORM
・TARGETARCH
あたりが必要になってくるので少しめんどくさいです。
# .NET SDKのImage(https://mcr.microsoft.com/product/dotnet/sdk/about)を指定, .NET CLI + .NET runtime + ASP.NET Coreから成り立つ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env ARG TARGETARCH WORKDIR /App # 全てのファイルをコンテナにコピーする COPY . ./ # csprojを見て依存関係を解決する RUN dotnet restore -a $TARGETARCH # ビルドしてpublishする RUN dotnet publish -c Release -o out -a $TARGETARCH # CloudRunSampleの実行 FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /App COPY --from=build-env /App/out . ENTRYPOINT ["dotnet", "CloudRunSample.dll"]
以下がファイル構成になっています。重要でないファイルは省いています。
. ├── CloudRunSample │ ├── CloudRunSample.csproj │ ├── Dockerfile │ └── Program.cs └── terraforms ├── main.tf ├── outputs.tf ├── provider.tf └── variables.tf
Artifact RegistoryにDocker Imageをアップロードする
Artifact Registory
にDocker Image
をアップロードします。
クイックスタート: Docker コンテナ イメージを Artifact Registry に保存する | Artifact Registry documentation | Google Cloud
まずはgcloud
がインストールされている前提でログインします。
$ gcloud auth login $ gcloud init
まだレポジトリを作成していない場合はレポジトリを作成する必要があります。
$ gcloud artifacts repositories create cloud-sample --location=asia-northeast1 --repository-format=docker
cloud-sample
は任意の名前にしてOKです。
以下コマンドでDocker用のArtifact Registory認証を行い、
# Docker用Artifact Registory認証 $ gcloud auth configure-docker asia-northeast1-docker.pkg.dev # docker buildの際に、Mac M1なら --platform linux/amd64 を付与してください $ docker build ./ -t asia-northeast1-docker.pkg.dev/{PROJECT_ID}/cloud-sample/cloud-sample-image # push $ docker push asia-northeast1-docker.pkg.dev/{PROJECT_ID}/cloud-sample/cloud-sample-image
Cloud RunのDocker Imageを変更する
image
を先程アップロードしたものに差し替えます。
# Cloud Runを構築する resource "google_cloud_run_v2_service" "default" { name = "sample" location = "asia-northeast1" ingress = "INGRESS_TRAFFIC_ALL" template { containers { image = "asia-northeast1-docker.pkg.dev/------:latest" } } }
最後に適応します。
$ terraform apply ... Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: service_url = "https://---.run.app"
最後にservice_url
にアクセスして、Hello, World
が表示されていたら成功です。
さいごに
今回はやりませんでしたがgoogle_artifact_registry_repository
あたりを使ってArtifact Registory
周りももっと自動化したいなと思ってます。
Terraform Registry