開発している積読ハウマッチ、Netlify+Nuxt(SPA)で作ってるけど、 SPAはやっぱり遅い感じが...
SSRにできて、リージョンも東京を選べるCloud Runを試してみたときの備忘録
Cloud Runについて
Google Cloud Runは、コンテナ化されたアプリをデプロイできるフルマネージド型プラットフォーム。
Dockerなどのコンテナイメージをデプロイして公開できる仕組み。
料金は、使用した分だけを払う従量課金制で、CPU/メモリ/リクエストなどそれぞれの合計。
無料枠も大きく、CPUだと最初の180,000 vCPU 秒は無料。
""請求先アカウントごとにプロジェクト間で合計され"" 、毎月リセットされるので注意。
""プロジェクトごとじゃない""
・料金 | Cloud Run のドキュメント | Google Cloud
Cloud Runにデプロイする
Cloud Runにデプロイできるようにする
Nuxtのガイドだとこのあたり
・How to deploy on Google Cloud Run? - NuxtJS
1. Cloud Run/Cloud Buildの有効化
まずは、機能の有効化。gcloud
コマンドで実行する。
# Enabling Cloud Run $ gcloud services enable run.googleapis.com # Enabling Cloud Build $ gcloud services enable cloudbuild.googleapis.com
古い記事だとCloud Runがベータ版の頃の記事があり、
コマンドにbeta
などついていることがあるので注意。
2. nuxt.config.tsの設定
環境変数で起動するポートとホストを設定できるように変更。
import { Configuration } from "@nuxt/types"; const config: Configuration = { // ... 略 // for GAE server: { port: process.env.PORT || 3000, host: process.env.HOST || "0.0.0.0", timing: false, }, }; export default config;
3. Dockerfileの作成
nuxt.config.ts
と同じ場所に、Dockerfileを作成。
FROM node:10 # コンテナ内のwork dirを設定 WORKDIR /src # 環境変数を設定し、ポートとホストを指定 ENV PORT 8080 ENV HOST 0.0.0.0 # package.jsonをコピーして、パッケージのインストール COPY package.json ./ RUN npm install # ソースをコピーして、ビルド COPY . . RUN npm run build # コンテナが起動したら、nuxtを起動するよう指定 CMD [ "npm", "run", "start" ]
これで一旦、コンテナ上での起動を確認
# コンテナのビルド $ docker build -t nuxt:1.0.0 . # コンテナイメージの確認 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE nuxt 1.0.0 8567b21340f4 12 seconds ago 1.98GB # コンテナの起動 $ docker run -d -p 8080:8080 --name nuxt nuxt:1.0.0
これで、 http://localhost:8080
で起動を確認できたらOK。
コンテナは停止/削除しておく。
# コンテナの停止 $ docker stop nuxt # コンテナの削除 $ docker rm nuxt # コンテナイメージの削除 $ docker rmi nuxt:1.0.0
まれにソースのコピーに失敗して、ビルドできない時がある。
.dockerignore
を用意するなどして、必要なものだけに絞るといいかも。
4. Container Registryにビルドしたコンテナを配置
Cloud Runで起動するためには、Container Registryに配置する必要がある。
gcloudコマンドで実行できる。こんな感じ。
$ gcloud builds submit --tag <GCR_HOST_NAME>/<PROJECT_ID>/<IMAGE_NAME> .
<GCR_HOST_NAME>
は、場所によって異なる。gcr.io
ではUS。asia.gcr.io
はアジアなど。
ドキュメントのこのあたり。
・Container Registry のドキュメント |レジストリ名
<PROJECT_ID>
は、GCPのプロジェクトIDを指定
<IMAGE_NAME>
は、イメージの名前で任意。末尾に:1.0.0
などバージョンを区別できる
今回の例だと、東京リージョンがいいので、以下のような感じ。
不要なファイルが送られないのように、.gcloudignore
も用意しておく。
# .gcloudignoreの作成 $ cp .gitignore .gcloudignore # or $ cp .dockerignore .gcloudignore # Container Registryにアップロード。末尾の.を忘れない $ gcloud builds submit --tag asia.gcr.io/sample-project/nuxt:1.0.0 .
結構長い。完了すると、以下のようなログになる。
DONE ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ID CREATE_TIME DURATION SOURCE IMAGES STATUS 9c9f5a49-de31-4ecd-8e87-710d3c2bbc2a 2020-09-03T20:18:51+00:00 5M31S gs://sample-project_cloudbuild/source/1599164294.784973-4c85cf396c404117b03c02398b3c1702.tgz asia.gcr.io/sample-project/nuxt:1.0.0 SUCCESS
Container Registryのイメージで起動できるかを確認
Container Registryのイメージでちゃんと起動できるかをローカルで確認する。
Container Registryにアクセスできるように、認証が必要。
$ gcloud auth configure-docker
ドキュメントだと、このあたり。
・認証方法 | Container Registry のドキュメント | Google Cloud
認証が完了したら、起動してみる。
$ docker run -p 8080:8080 --name nuxt --rm asia.gcr.io/sample-project/nuxt:1.0.0
これで、 http://localhost:8080
で起動を確認できたらOK。
上記と同様に、コンテナやイメージを停止/削除しておく。
ローカルでのテスト方法のドキュメントはこの辺り。
・コンテナ イメージをローカルでテストする | Cloud Run のドキュメント | Google Cloud
5. Cloud Runにデプロイする
やっと準備が整ったので、Cloud Runにデプロイ。
Container Registryを指定して、gcloud
コマンドを実行。
$ gcloud run deploy --image=asia.gcr.io/sample-project/nuxt:1.0.0 --platform managed --port 8080 --region asia-northeast1
--platform
は、通常であればmanaged
を指定。Cloud Run for Anthosを使うはgke
などを指定する
--region
は、リージョンの指定。asia-northeast1
は東京リージョン。
他のリージョンは、以下のドキュメントを参照。
・Cloud Run のロケーション | Cloud Run のドキュメント | Google Cloud
実行すると、以下のようなプロンプトが表示される。
2つ目は、認証無しでアクセスできるかをなので、y
を選択する。
Service name (nuxt): Allow unauthenticated invocations to [nuxt] (y/N)?
うまくデプロイできると、以下のように表示されるので、
URLにアクセスして確認する。
Done. Service [nuxt] revision [nuxt-00001-waf] has been deployed and is serving 100 percent of traffic at https://nuxt-usdf3rusd-an.a.run.app
Cloud RunにデプロイするのこれでOK!!
6. Cloud BuildとGitHubを使った自動デプロイ
Cloud Buildのトリガーを利用することで、masterにpushしたらデプロイすることもできる。
ドキュメントだと以下のあたり。
・Cloud Build を使用した Git からの継続的なデプロイ | Cloud Run のドキュメント | Google Cloud
・ビルドトリガーの作成と管理 | Cloud Build のドキュメント | Google Cloud
ビルド構成ファイルの作成
まずは、構成ファイルを作成する。
Dockerfileと同じ階層にcloudbuild.yaml
を作成。
中身はこんな感じ。steps
配下に手順を記載していて、
- コンテナイメージのビルド
- Container Registryでアップロード
- Cloud Runへのデプロイ
をやっている感じ。
steps: # Build the container image - name: gcr.io/cloud-builders/docker id: Build args: - build - "--no-cache" - "-t" - "$_GCR_HOSTNAME/$PROJECT_ID/$_SERVICE_NAME:$COMMIT_SHA" - . - "-f" - Dockerfile # Push the container image to Container Registry - name: gcr.io/cloud-builders/docker id: Push args: - push - "$_GCR_HOSTNAME/$PROJECT_ID/$_SERVICE_NAME:$COMMIT_SHA" # Deploy container image to Cloud Run - name: gcr.io/google.com/cloudsdktool/cloud-sdk id: Deploy entrypoint: gcloud args: - run - services - update - $_SERVICE_NAME - "--platform=managed" - "--image=$_GCR_HOSTNAME/$PROJECT_ID/$_SERVICE_NAME:$COMMIT_SHA" - "--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS" - "--region=$_DEPLOY_REGION" - "--quiet" images: - "$_GCR_HOSTNAME/$PROJECT_ID/$_SERVICE_NAME:$COMMIT_SHA" options: substitutionOption: ALLOW_LOOSE tags: - gcp-cloud-build-deploy-cloud-run - gcp-cloud-build-deploy-cloud-run-managed
ファイル内では変数も利用でき、各変数は以下のドキュメントに記載されている。
・変数値の置換 | Cloud Build のドキュメント | Google Cloud
GitHub連動とトリガーの作成
Cloud Runの画面の「継続的デプロイの設定」から設定できる。
この段階では、Build Typeにcloudbuild.yaml
を設定できないので、
同じ場所にある「継続的デプロイを編集」から変更する。
これで、pushしてみて、Cloud Buildの履歴を見ながら、動作するかを確認する。
ハマったり悩んだりしたところ
アクセスが少ないとコールドスタートが発生して遅い
Cloud Runで請求される時間は、リクエストを処理している間になる。
処理するリクエストがないと、インスタンスが停止する。
そのため、料金は加算されなくなるが、次にリクエストがきたときにコールドスタートになる。
必要な分だけの請求になるけど、稼働していないと遅いので、悩みどころ。
自分の場合、PCからアクセスしてもコールドスタートだと5~6秒くらいかかる。。
コールドスタートについては、以下の記事が参考になった。
Schedulerによる停止の抑止など対策もいくつか記載されている。
・ [Cloud OnAir] Cloud Run Deep Dive ~ GCP で実践するモダンなサーバーレス アプリケーション開発 ~…
Cloud Buildなどで利用したファイルはStrageに保存される
アップロードしたソースやコンテナイメージは、Google Storageに保存されるので注意。
なにもしないと、どんどんファイルが増えていき、保存量で課金が発生していく。
・<PROJECT_ID>_cloudbuild
バケットへ、ローカルからアップロードするとソースが配置され、
・asia.artifacts.<PROJECT_ID>.appspot.com
にasia.gcr.io
のコンテナイメージが配置される
オブジェクトのライフサイクル管理で自動削除などもできるので、設定するのがいい。
Cloudflareを利用する場合は、ポート3000ではだめ
Cloudflareを利用する場合は注意が必要。
HTTPとして扱うポートが決まっているので、3000ではだめ。
・Identifying network ports compatible with Cloudflare's proxy – Cloudflare Help Center
そのため、8080を設定している。
CloudflareでSSL/TLS 暗号化モードはFull
Cloudflareで暗号化モードはいくつかあるが、
フレキシブルを選択すると、リダイレクトループになる。
・リダイレクトループエラーのトラブルシューティング – Cloudflareヘルプセンター
さらに、Cloud Runのドキュメントを見ると、以下の設定も確認が必要
注: サードパーティの CDN プロバイダによっては、誤って検証リクエストをインターセプトする可能性があります。
その場合、Cloud Run サービスに到達できなくなり、ドメイン マッピングや証明書の更新に失敗します。
たとえば、Cloudflare CDN を使用する場合、
[SSL/TLS] タブの [Edge Certificates] で [Always use https] オプションをオフにする必要があります。
また、カスタムドメインにマッピングしたあと、GCP側でSSL証明書のプロビジョニングがおこなわれる。
プロビジョニング中は、Cloudflareから525が返される。。
・カスタム ドメインのマッピング | Cloud Run のドキュメント | Google Cloud
Container Registryのパスに不要なスラッシュがあるとエラーになる
Container Registryのパスは決まっていて、
<GCR_HOST_NAME>/<PROJECT_ID>/<IMAGE_NAME>
でないとエラーになる。
置換できる変数値にブランチ名($BRANCH_NAME
)が利用できるので、
それを使おうとしたら、ブランチ名にスラッシュが入っていてエラーに...
変数値に対してbash 形式の文字列操作ができるようだけど、うまくいかず断念。。
Firebase HostingとCloud Runを連動させる
Firebase HostingのリクエストをCloud Runにリダイレクトさせることできる。
Firebase Hostingは、グローバルCDNが利用されるので、Cloudflareなどを利用しない場合によい。
ドキュメントだとこの辺り。
・Cloud Run を使用した動的コンテンツの配信とマイクロサービスのホスティング | Firebase
firebase.jsonのhosting
部分にrewrites
を追加すればOK
"hosting": { // ... // Add the "rewrites" attribute within "hosting" "rewrites": [ { "source": "**", "run": { "serviceId": "helloworld", // "service name" (from when you deployed the container image) "region": "us-central1" // optional (if omitted, default is us-central1) } } ] }
Slackでの通知もできるらしい
試していないけど、Cloud BuildでSlackなどの通知処理を組み込めるよう。
ドキュメントのこのあたり。
・Slack 通知を構成する | Cloud Build のドキュメント | Google Cloud
Cloud RunとGAEのどちらがよいかのフローチャート
以下のドキュメントに選定基準がのってる。 ・サーバーレス オプションの選択 | Serverless Guide | Google Cloud
ここをみると、
- k8sが不要で、特別なシステムライブラリが不要なら、GAE
- そうでなければ、Cloud Run
のよう。GAEで動かせなければ、コンテナを使えるCloud Runがよさそう。
さらにいえば、上記のコールドスタートの問題が気にならなければいいかもしれない。
GAEでもコールドスタートの問題があるが、ウォームアップ リクエストなるものがあるので、軽減できる余地がある。
・ウォームアップ リクエストを構成してパフォーマンスを改善する
また、無料枠的にも、Cloud Runはフル稼働させると2日しか持たないので、
コールドスタートが許容できるかが目安になるかもしれない。
以上!!
参考にしたサイト様
- Cloud Run+Nuxt
- コールドスタートの話
- Cloud Build
- Cloud Runのトラブルシューティング