5. Cloud Runへデプロイする
4章で作ったイメージを Artifact Registry に push し、Cloud Run にデプロイして、世界中からアクセスできる HTTPS URL を手に入れます。
0. 環境変数の準備
この先の章でも使うので、まとめて設定しておきます(Cloud Shell が切断された場合はここから再実行してください)。
export PROJECT_ID=$(gcloud config get-value project)
export REGION=asia-northeast1 # 東京リージョン
export REPO=handson
export IMAGE=${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO}/app
成功していれば:
echo ${IMAGE}でasia-northeast1-docker.pkg.dev/<プロジェクトID>/handson/appの形が表示されます(<プロジェクトID>の部分には自分のプロジェクトIDが入ります)。
詰まったら:asia-northeast1-docker.pkg.dev//handson/appのようにプロジェクトIDの部分が抜けている場合は、gcloudにプロジェクトが設定されていません。gcloud config set project <プロジェクトID>を実行してから、この節のコードブロックを再実行してください(プロジェクトIDの確認方法は3章の「5. 動作確認」を参照)。
asia-northeast1= 東京です。AWS のap-northeast-1と対応が覚えやすいですね。
1. Artifact Registry にリポジトリを作る
ECR と同じく、イメージの置き場をまず作ります。
gcloud artifacts repositories create ${REPO} \
--repository-format=docker \
--location=${REGION} \
--description="Cloud Run handson"
docker コマンドが Artifact Registry に push できるよう、認証ヘルパーを設定します(ECR の aws ecr get-login-password に相当。こちらは一度設定すれば、push のたびにトークンを取り直す必要はありません)。
gcloud auth configure-docker ${REGION}-docker.pkg.dev
成功していれば: リポジトリ作成が
Created repository [handson].で終わり、gcloud artifacts repositories list --location ${REGION}にhandsonが1行表示されます。認証ヘルパーの設定はDocker configuration file updated.で終わります。すでに設定済みの環境ではgcloud credential helpers already registered correctly.と表示されますが、こちらも成功です。
詰まったら:ALREADY_EXISTSは作成済みという意味なので、そのまま次へ進んで構いません。PERMISSION_DENIEDや API 無効のエラーが出た場合はgcloud services enable artifactregistry.googleapis.com run.googleapis.comを実行してから作成コマンドを再実行してください。${REPO}や${REGION}が空文字で展開されている(コマンドがcreate --location=のように見える)場合は、Cloud Shell の再接続で環境変数が消えています。「0. 環境変数の準備」を再実行してください。
2. イメージにタグを付けて push する
Artifact Registry のイメージパスは リージョン-docker.pkg.dev/プロジェクト/リポジトリ/イメージ名:タグ という形式です。
4章で作ったイメージにこのパスでタグを付け直して push します。
cd ~/cloudrun-handson/app
docker tag handson-app:v1 ${IMAGE}:v1
docker push ${IMAGE}:v1
初回の push はイメージ全体を転送するため、目安として数十秒から1分ほどかかります。
push できたか確認してください。
gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO} --include-tags
コンソールの Artifact Registry からも見えます。
成功していれば:
docker pushの最後がv1: digest: sha256:... size: ...で終わり、gcloud artifacts docker images listの出力に.../handson/appの行が1つ表示され、TAGS列がv1になっています。
詰まったら:An image does not exist locally with the tag: handson-appと出た場合は4章のイメージが手元にありません。cd ~/cloudrun-handson/app && docker build -t handson-app:v1 .でビルドし直してから、タグ付けと push をやり直してください(手元のイメージ一覧はdocker imagesで確認できます)。deniedやunauthorizedが出る場合はgcloud auth configure-docker ${REGION}-docker.pkg.devを実行してからdocker push ${IMAGE}:v1を再実行します。echo ${IMAGE}が空、または-docker.pkg.dev//のように途中が抜けている場合は「0. 環境変数の準備」を再実行してください。
3. Cloud Run にデプロイする
いよいよ本番です。
このコマンド1つで、ECS なら ALB・ターゲットグループ・ACM 証明書・サービス・タスク定義を組み立てていた作業がすべて終わります(1章の発展コラムで触れた ECS Express Mode を除く)。
gcloud run deploy handson-app \
--image ${IMAGE}:v1 \
--region ${REGION} \
--allow-unauthenticated
handson-appが Service 名になります--allow-unauthenticatedは「認証なしで公開」。デフォルトは IAM 認証必須(=閉じている)で、AWS と逆のデフォルトです
30秒ほどで完了し、Service URL: https://handson-app-<プロジェクト番号>.asia-northeast1.run.app のような URL が表示されます。
成功していれば: 出力の最後に
Service [handson-app] revision [handson-app-00001-xxx] has been deployed and is serving 100 percent of traffic.と Service URL が表示されます。URL はサービス名-プロジェクト番号.リージョン.run.appという決まった形式です。あとからgcloud run services describe handson-app --region ${REGION} --format 'value(status.url)'でいつでも取り直せますが、こちらはhandson-app-<ランダム文字列>-an.a.run.appという古い形式の URL を返します。どちらも同じ Service を指す有効な URL なので、見た目が違っても気にしなくて大丈夫です(7章以降ではdescribeで取得した URL をそのまま使います)。
詰まったら: まずgcloud run services list --region ${REGION}で Service が作られているか確認してください。作られていなければエラーの原因を切り分けます。Image not foundやmanifest unknownの場合は「2. イメージにタグを付けて push する」の push が完了していないので、gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO} --include-tagsを実行し、TAGS列にv1が付いた行があるかを確認してください。--regionや--imageが空で怒られる場合は「0. 環境変数の準備」を再実行します。設定を間違えた場合も、同じgcloud run deployコマンドを何度でも実行し直して大丈夫です(新しいリビジョンが作られて上書きされます)。
いまデプロイした Service は、2章で触れた2つの課金モデルのうち既定の request-based billing(リクエスト処理中だけ CPU が割り当てられ、その分だけ課金される方式)で動いています。
常時処理があるワークロード向けの instance-based billing に切り替えるには、gcloud run deploy に --no-cpu-throttling を付けて CPU を常時割り当てます(作成済みの Service でも gcloud run services update で切り替えられます)。
今日のハンズオンでは切り替えません。
4. アクセスして確認する
表示された URL をブラウザで開いてください。
4章で Cloud Shell の中で見たのと同じ青い画面が、今度は本物のインターネット越しに表示されます。
4章との違いを見てください:
Serviceがhandson-appに、Revisionがhandson-app-00001-xxxになっている(Cloud Run が注入する環境変数K_SERVICE/K_REVISIONをアプリが表示している)- URL が最初から HTTPS。証明書の発行も更新も何もしていない
コンソールの Cloud Run のページ も開いてみてください。
Service の一覧、リビジョン、メトリクス、ログがすべて1画面に集約されています。
ふりかえり: 何をしなかったか
ここまでで「したこと」はリポジトリ作成 → push → deploy の3コマンドです。
それより「しなかったこと」に注目してください。
- VPC・サブネット・セキュリティグループを作らなかった
- ロードバランサーもリスナーも作らなかった
- TLS 証明書を発行しなかった
- タスク定義(CPU/メモリ/ポート)を書かなかった ※デフォルト値で開始し、必要なら後から変える
- キャパシティ(台数)を決めなかった
- タスク実行ロール・タスクロールを分けて作らなかった ※Service には既定のサービスアカウント(Compute Engine のデフォルトサービスアカウント)が1つ付くだけ(1章の対比)
最後の1つは確認できます。gcloud run services describe handson-app --region ${REGION} --format 'value(spec.template.spec.serviceAccountName)' を実行すると、<プロジェクト番号>-compute@developer.gserviceaccount.com の形のサービスアカウントが1つだけ表示されます(コンソールでは Service の詳細画面の「セキュリティ」タブで同じものが見えます)。
1章で話した「ビルディングブロック vs SaaS的アプローチ」が、これで体感できたはずです。