Help us understand the problem. What is going on with this article?

CloudRunならたった5分でwebアプリをリリースできちゃう~消去しりとりサービスをCloudRunでリリースした時の備忘録~

はじめに

GoogleからDockerコンテナをサーバレスで実行できるCloudRunが公開されたので触ってみようと思ったところかなり使いやすくて、自分でサービスを立ち上げたので、その時の備忘録を記載していこうと思います。

今回はNodeJSの公式イメージを元にNodeJS + Expressでアプリケーションを作成し、Dockerコンテナを作成してCloudRunに乗せるまでを記載します。
また、今回はNodeJSのアプリケーションの説明を目的とはしていませんので、そこについては触れません。

記事の最後に作成したアプリケーションの宣伝をしています🙇‍♂️
もし、本当にお時間がある上に暇な場合に少しでも見てやってもいいかなと思ったら見てやってください🙇‍♂️🙇‍♂️

対象読者

以下のような方が対象となるかもしれません。

  • インフラわからないけどアプリを公開してみたい
  • てっとり早く公開したい
  • サーバレスを経験してみたい
  • 新しいサービス触ってみたい

ご自身でサーバを立ち上げて、webサーバ等のミドルウェアを構築したい方は以下の記事が参考になるかもしれません。

CloudRunについて

CloudRunとはGoogle Cloud Next'19で発表されたDockerコンテナをサーバレス環境で実行できるサービスです。
HTTPでリクエストを受ける事が可能なステートレスコンテナを実行できます。

Knativeから作成されており、開発者はCloudRunを使用してフルマネージド型でコンテナを実行するか、GKEクラスタ上にデプロイする事が可能です。
CloudRunによる管理の場合は、開発者がインフラを意識せずに利用ができ、トラフィックに応じてスケールアップやスケールダウンも自動的に実行してくれます。なのでスケーリング構成のことを心配する必要はありません。

詳しい内容は公式ドキュメントを読んでください
CloudRunの公式ドキュメント

料金について

Cloud Run の課金対象は使用したリソース(100 ミリ秒単位、1,000 ミリ秒単位以下切り捨て)に限られるため、過剰にプロビジョニングしたリソースに料金を支払う必要はありません。

無料枠も用意されているので、過度なアクセスが来ない限りは無料で利用することができます。
無料枠としては、以下の通りになっています。

CPU Memory Requests
180,000 vCPU 秒/月 360,000GB/月 200 万回リクエスト数/月

詳しくは以下のドキュメントをご覧ください
CloudRunの料金

最速でアプリをデプロイするまで

前置きが長くなってしまいましたが、早速アプリをCloudRunで公開してみようと思います。

事前準備

CloudRunを利用するために以下の事前準備を行いましょう。

1. GCPアカウントを作成

作りましょう。

2. GCPのプロジェクトを作成

リソース管理ページから以下の画像の赤枠のリンクからプロジェクトを新規に作成しましょう。
スクリーンショット 2019-09-16 3.33.16.png

3. プロジェクトに対して課金を有効にする

こちらのページから課金を有効にしましょう。

4. CloudRunAPIを有効にする

こちらから"有効にする"を押してAPIを有効にしましょう。
スクリーンショット 2019-09-16 3.41.08.png

5. Cloud SDKをインストール

以下のページ の手順にしたがってCloud SDKをインストールしましょう。
https://cloud.google.com/sdk/docs/

6. gcloud betaをインストール

以下のコマンドを実行し、gcloud betaをインストールする。

$gcloud components install beta

7. componentsをupdate

以下のコマンドを実行し、componentsをアップデートする。

$gcloud components update

8. platformとregionをset

platformとregionを設定しておきましょう。
regionですが、現在cloudrunを実行できるregionは以下から選べます。

  • asia-northeast1 (Tokyo)
  • europe-west1 (Belgium)
  • us-central1 (Iowa)
  • us-east1 (South Carolina)
gcloud config set run/platform managed
gcloud config set run/region {REGION}

9. アプリケーションを用意しておく

今回はNodeJSで簡単なアプリを作って動かしてみたいと思います。
(nodeの実行環境は用意しておいてください。)

適当な作業ディレクトリに移動して以下のコマンドを実行します。

$ mkdir test-app && cd test-app
$ touch index.js

そして好きなエディタでindex.jsを開いて"Hello World!"を表示するだけの以下のコードを書きましょう。

index.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello World!');
});

const port = process.env.PORT || 8080;
app.listen(port, () => {
  console.log('Listening on port', port);
});

最後にpackage.jsonを作成しましょう。

npm initしてnpm install expressを実行する か
以下のコードをpackage.jsonに記載しましょう。

package.json
{
  "name": "test-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}

ここまでで事前準備は完了です!
ではデプロイしましょう。

Step1: Dockerfileを用意

事前準備通りに準備した場合は以下のようなDockerfileで上手く行くかと思います。
test-appディレクトリ直下にDockerfileを作成して中身に以下のように記述しましょう。

FROM node:12-slim

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install --only=production

COPY . ./

CMD [ "npm", "start" ]

このDockerfileを元にコンテナを起動させるといらないものまでコンテナ側に渡してしまうことになるので、.dockerignoreも用意しておきましょう。

.dockerignore
Dockerfile
README.md
node_modules

Step2: コンテナをBuildし、GCRにuploadする

  1. Cloud Build APIをあらかじめ有効にしておきましょう。

  2. GCPで作成したプロジェクトのプロジェクトIDを控えておいてください。

  3. Dockerfileを配置したディレクトリで以下のコマンドを実行し、コンテナをBuildします。
    成功するとGCR(Google Container Registry)にアップロードされます。

    • ${PROJECT_ID}にはGCPのプロジェクトIDを記載してください。
    • helloworldの部分も適宜変えてください。
$ gcloud builds submit --project ${PROJECT_ID} --tag gcr.io/${PROJECT_ID}/helloworld

成功すると以下のようにSUCCESSと標示されると思います。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ID                                    CREATE_TIME                DURATION  SOURCE                                                                                         IMAGES                                           STATUS
26*****0f-4**1-4**2-a**c-9*******ad  2019-09-15T20:23:30+00:00  35S       gs://clo****************ld/source/15*****7.36-270*******************a37.tgz  gcr.io/clo*************18/helloworld (+1 more)  SUCCESS

Step3: CloudRunにデプロイ

実際にCloudRunにデプロイしましょう。

  • 以下のコマンドを実行してください。
    • ${PROJECT-ID}はStep2で控えておいたプロジェクトIDに置き換えてください。
    • また、helloworldをStep2で変更していた場合はその名前に変更してください。
$ gcloud beta run deploy --image gcr.io/${PROJECT-ID}/helloworld --platform managed
  • 上記コマンドを実行するとサービス名を聞かれるので、任意のサービス名を入力しましょう。
Service name (helloworld): ~サービス名~
  • あとは聞かれた質問に答えましょう

    • regionを聞かれた場合は、事前準備で選択したregionを記載しましょう
    • allow unauthenticated invocationsを聞かれた場合は、y/Nのどちらかで回答しましょう。
      • 今回作成するアプリケーションは認証なく呼べていいものなので"y"でよいかと思います。
  • デプロイが完了するとURLが表示されるのでアクセスしてみてください

    • Hello World!と表示されていれば無事に公開できています。 スクリーンショット 2019-09-16 5.42.16.png

お疲れ様です!
どうでしょう?
そんなにステップもなく簡単にデプロイできたのではないでしょうか?

表題の通り5分でリリースできましたね!(事前準備をなくせば)

(Appendix) デプロイの自動化

ここまでで一旦デプロイが完了し、アプリケーションにリクエストすることができますが、
デプロイするために毎回毎回上記の処理をするのは少し面倒ではあるので、
ここからはおまけとして、
githubのmasterブランチにpushされたタイミングで自動的にデプロイされるような仕組みを組み立てたいと思います。

全体の構成

イメージとしては以下のような構成図になります。
スクリーンショット 2019-09-16 17.38.12.png

流れとしては
1. githubのmasterにpushされたのをトリガーにCloud Buildを実行
2. Cloud BuildでDockerイメージのビルドを実行し、GCRにpush
3. GCRからCloudRunにデプロイ

の3ステップを自動化させることになります。
それではやっていきましょう。

事前準備

デプロイの自動化を行うために事前準備が必要なので、
以下の通りに準備を進めていきましょう。

APIの有効化

以下二つのAPIを有効化しておきましょう。
* Cloud Run APIの有効化
* Cloud Resource Manager APIの有効化

サービスアカウントの権限設定

IAMの管理から{ProjectID}@cloudbuild.gserviceaccount.com)に
以下の権限を追加してください。

  • Cloud Run 管理者
  • Cloud Run サービスエージェント
  • ストレージオブジェクト 閲覧者

以下のような状態になっていれば大丈夫です。
スクリーンショット 2019-09-16 19.45.31.png

cloudbuild.ymlを作成

cloudbuild.ymlとは

cloudbuild.yamlはCloud Buildが公式にサポートするデフォルト設定ファイルです。
このファイルを利用してトリガーを作成してDockerイメージをビルドします。
今回はDockerfile + cloudbuild.ymlの組み合わせでCI/CDを行います。

cloudbuild.yamlの主な役割は、Dockerfileを実行し、ビルドしたイメージをGCRにPushして、CloudRunにデプロイを行います。

cloudbuild.ymlの作成

それではcloudbuild.yamlを アプリケーションのあるディレクトリのいずれかに作成しましょう。
今回の例ではアプリケーションルートにおいた例を記載します。

~ test-appディレクトリに移動 ~

$ touch cloudbuild.yaml

そしてcloudbuild.yamlに以下にのように記載します。

cloudbuild.yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    id: 'build-docker-image-from-dockerfile'
    args: 
      - 'build'
      - '-t'
      - 'gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$SHORT_SHA'
      - '.'
  - name: 'gcr.io/cloud-builders/docker'
    id: 'push-docker-image-to-gcr'
    args: 
      - 'push'
      - 'gcr.io/$PROJECT_ID/${_SERVICE_NAME}'
  - name: 'gcr.io/cloud-builders/gcloud'
    id: 'deploy-cloud-run'
    args: 
      - 'beta'
      - 'run'
      - 'deploy'
      - '${_SERVICE_NAME}'
      - '--image'
      - 'gcr.io/$PROJECT_ID/${_SERVICE_NAME}:$SHORT_SHA'
      - '--platform'
      - 'managed'
      - '--region'
      - 'us-central1'
substitutions:
  _REGION: us-central1
  _SERVICE_NAME: helloworld

内容を説明するとstepsの内容が順番に実行されていきます。
今回は3つステップが存在していてそれぞれ以下のような役割を実行します。

  1. Dockerfileを元にDockerイメージをビルド
  2. DockerイメージをGCRにpush
  3. GCRからDockerイメージをCloud Runへデプロイ

また、cloudbuild.yamlに記載するフィールドを少し解説すると
stepのnameフィールドは、クラウド ビルダーを指定するために使用します。

例えば
gcloudを実行したい場合には
- name: 'gcr.io/cloud-builders/gcloud'

dockerを実行したい場合には
- name: 'gcr.io/cloud-builders/docker'
と記載します。

また、argsフィールドには上記のnameフィールドに記載したコマンドに続くコマンドを","区切りで記載します。
例えば、
docker build -t hoge .の場合には以下のように記載します。

steps:
  - name: 'gcr.io/cloud-builders/docker'
  - args:
      - 'build'
      - '-t'
      - 'hoge'
      - '.'

最後にidフィールドですが、
そのstepの識別子として利用するのでわかりやすい名称をつけてあげると良いかと思います。

CloudBuildのトリガーを作成

cloudbuild.ymlまで作成し終えたらCloudBuildにトリガーを作成します。
CloudBuildのトリガーページを開いて以下画像のトリガーを追加を選択します。
スクリーンショット 2019-09-16 20.21.44.png

次のページでgithubを選択して同意するにチェックをいれた状態で続行を押します。
スクリーンショット 2019-09-16 20.23.39.png

少しの間認証が完了するのを待ち、以下の画面が出たら、今回のアプリケーションを管理しているgithubのレポジトリを選択し、続行を押します。
スクリーンショット 2019-09-16 20.24.05.png

そうすると以下の画面が出るので、どのブランチへのpushをトリガーにするかやcloudbuild.yamlの場所を決定していきます。
masterブランチへのpushをトリガーにする かつ アプリケーションルートにcloudbuild.yamlをおいている場合には以下の設定にすれば大丈夫です。
スクリーンショット 2019-09-16 20.29.47.png

ここまでできたら保存を押して設定は完了です。

githubのmasterブランチにpush

ここまでであらかたの設定は完了しているので、正しく動作しているかを確認するためにmasterブランチにpushしてみてください。
正しくCloudRunにデプロイされていれば成功になります。

お疲れ様でした!

ちょっと宣伝

以下はちょっとした宣伝になります。
今回は上記までの構成でオンライン対戦型のしりとりゲームを作成してみました。

消去しりとり
スクリーンショット 2019-09-16 20.39.29.png

めだかボックスのデリートテールトゥノーズのようなしりとりを
自分でやってみたくて作成したものになります。
ルールを多少変えて難易度を下げていますが、それなりに難しく結構面白いので、
ぜひ遊んでみてください!

参考文献

GCPのCloud Buildを使おう

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away