17
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ServerlessAdvent Calendar 2020

Day 14

【GCP初心者向け】Cloud Runでサーバーレスな超簡易Web APIを無料で作る

Last updated at Posted at 2020-12-18

自分用の簡易なWeb APIが必要になり、GCPのCloud Runを初めて触ったので、記録として手順をまとめて公開しておくことにしました。

この記事で作るもの

GCP初心者向けの記事です。Cloud RunをWeb APIとして使用し、ローカルから**「こんにちは」とPOSTリクエストすると「こんにちはと言いましたね。」と返してくる超簡単なWeb API**を作ります。
00.jpg
ここで作るのは簡単なAPIですが、要するに入力と出力を整えれば、あとはいくらでも応用して処理が書けるので、その重要なインターフェース部分を作る手順です。

はじめに ~Cloud Runとは~

Web APIをサーバーレスで簡単に実現するには、AWS LambdaとAPI Gatewayを組み合わせる、またはGCP Cloud FunctionsやGAEという場合が多いかと思います。
ただしカスタムのライブラリが必要となる場合はAWS Fargate、更に無料でやるのはGCP Cloud Runという選択肢になります。

Cloud Runは呼び出されたときにコンテナを実行するというサービスです。要は、カスタムのライブラリを詰め込んだり、カスタムのデータを持たせて読み込ませて処理させる、といった使い方が可能です。またWeb API化でき、公開可能です。

AWSでいうとFargateやLambda(コンテナ)とAPI Gatewayが一緒になったサービスで、GCPの場合は永久無料枠が用意されているといった感覚です。なお詳しいユースケースは以下に記載されてます。
https://cloud.google.com/serverless-options/?hl=ja

ただし公開するWeb APIとなると、永久無料枠の場合はアクセス過多の際にスペックが貧弱すぎるため向いていません。
そこで自分がバッチ処理で使うWeb APIとして、Cloud Runを使うまでの手順を記載していきます。

Cloud Runの永久無料枠

Cloud Runは永久無料枠が用意されています。他のクラウドサービスはここまで太っ腹じゃないですね。

200 万リクエスト(1 か月あたり)
360,000 GB 秒のメモリ、180,000 vCPU 秒のコンピューティング時間
1 GB の北米からの下り(外向き)ネットワーク(1 か月あたり)

https://cloud.google.com/run/pricing?hl=ja

コンテナをずっと起動させておく場合はお金がかかってしまいますが、呼び出されたときのみコンテナを起動させる、1日に数回走るバッチ処理で使用するといった使い方であれば無料でいけるでしょう。

Cloud RunでWeb APIを作ろう

実際にCloud RunをWeb APIとして動かすまでには、以下の手順が必要になります。

  1. POSTリクエストを受け付けるコードを書く
  2. Web APIサーバーとしてのDockerfileを書く
  3. GCP上でDockerコンテナイメージをビルド+プッシュする(Container Registory)
  4. Cloud Runで新規サービスを作成し、イメージをデプロイする

PythonスクリプトとDockerfileについては、以下のとても分かりやすい記事をベースにして、POSTリクエストに対応させるために書き換えています。
Cloud Runに入門してみる

POSTリクエストを受け付けるコードを書く

まずは簡単に、POSTリクエストで送られてきたデータを処理し、返却するコードを書きます。json形式でリクエストされたdataキーの値を読み、「あなたは○○と送ってきましたね。」と返してきます。Python+flaskで書きます。

例えばローカルに./run-webapiディレクトリを作り、その配下に、以下のコードが書かれたhello-api.pyを配置しておきます。

hello-api.py
import os
from flask import Flask, request

app = Flask(__name__)


@app.route('/', methods=['POST'])
def post_response():
    request_dict = request.get_json()
    req_data = str(request_dict['data'])
    res_message = f'あなたは{req_data}と送ってきましたね。'
    return res_message


if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 5000)))

Web APIサーバーとしてのDockerfileを書く

次に./run-webapi配下に、以下のDockerfileを配置します。これでコンテナ起動時にhello-api.pyが実行され、コンテナはWeb APIサーバーとなります。

Dockerfile
FROM python:3.7

ENV APP_HOME /hello-api
WORKDIR $APP_HOME
COPY . .

RUN pip install Flask gunicorn
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 hello-api:app

GCP上でのコンテナイメージのビルド

プロジェクト作成

まずはGCPのコンソールから新しいプロジェクトを作成します。(既存のプロジェクトにコンテナをビルドしたい人はもちろんスキップ)
01.jpg

プロジェクト名はhellowebapiになりました。

コンテナイメージのビルド+ブッシュ

次にGCP上にコンテナイメージをビルドし、保存します。ローカルでビルドする必要はありません
コンソールで、./run-webapi配下に移動し、Google Cloud SDKのコマンドを入力します。
(※Google Cloud SDKがインストールされている前提です。詳しくはこちら https://cloud.google.com/sdk/docs/install?hl=JA

$ cd ./run-webapi
$ gcloud builds submit --tag gcr.io/hellowebapi/hello-api --project hellowebapi

ビルド+プッシュが完了した段階で、Container Registory上にhello-apiの名前でコンテナイメージが保存されます。
02.jpg

Cloud Runに登録済みコンテナをデプロイする

最後に、Container Registoryに登録したコンテナをCloud Run上にデプロイし、ようやくWeb APIを作ります

ウェブコンソール画面上の「サービスの作成」をクリックします。
03.jpg

①サービスの設定

デプロイメント プラットフォーム:Cloud Run(フルマネージド)
リージョン:us-central1 (Iowa)
サービス名:webapi-test
04.jpg

②サービスの最初のリビジョンの構成

既存のコンテナ イメージから 1 つのリビジョンをデプロイする:hello-apilatest
05.jpg

③このサービスをトリガーする方法の構成

HTTP上り(内向き):全てのトラフィックを許可する
認証:未認証の呼び出しを許可
06.jpg

なおここでは一旦、全ての認証を許可します。当然ですがセキュリティ上、本来は自分用のAPIの場合には認証をつけた方が良いですが、認証手順をすっ飛ばして使うために、アドレスを公開しないことを前提に未認証を許可します。

上記の設定を入力後、「作成」ボタンをクリックします。

1分後くらいに、ステータスが緑色になってURL「https://webapi-test-xxxxxx.a.run.app」が表示されます。これがWeb APIのURLとなります。
07.jpg

Web APIを試す

ではローカル環境から、いま作ったCloud Run上のWeb APIを呼び出してみましょう。
JupyterNotebook上で以下のコードを実行してみます。

JupyterNotebook上
import requests
import json

json_data = json.dumps({'data':'「ローカル環境からこんにちは」'})
response = requests.post(
    'https://webapi-test-xxxxxx.a.run.app', # 自分のWeb APIのURLに書き換え
    json_data,
    headers={'Content-Type': 'application/json'}
)

print(response.text)

以下の結果が返ってくれば成功です。

結果
あなたは「ローカル環境からこんにちは」と送ってきましたね。

ちなみにコンテナの初回起動には数秒くらいかかります。初回から連続でリクエストを送る場合は、既にコンテナが起動しているのでレスポンスは速いです。
コンテナはしばらくすると自動で停止します。そうして料金が抑えられるわけですね。

コンテナが自動でスケールしないようにするために

Cloud Runの標準スペックは貧弱で、vCPU 1コア、RAMが256MBが標準です。そのため重い処理が走る場合、自動でスペックをスケールさせる機能があります。
まったりでもよいから無料の範囲で抑えたい、という場合は、スケールをさせないようにする必要があります。

ウェブコンソール画面上の「新しいリビジョンの編集とデプロイ」を押します。
08.jpg
「自動スケーリング」の「インスタンスの最大数」を1に設定し、「デプロイ」を押します。
09.jpg
そうすることで、重い処理だとしてもスケールせずに1インスタンスで処理をするようになります。

注意事項:ストレージ容量に気を付けましょう

Cloud Runが無料とは言え、気を付けなければいけないちょっとした落とし穴があります。
登録済みのコンテナイメージはContainer Registoryで見られますが、実際のファイルはCloud Storageに保存されています
Cloud Storageの永久無料枠は5GBですので、ポンポンとコンテナイメージを作っているとすぐに一杯になるので気を付けた方が良いですね。

おわりに

Cloud Runを利用すればものすごく簡単にWeb APIが無料で作れます。
私は「コンテナに簡易DBのような割と大きめのデータを持たせておき処理をする」という必要があり、Cloud FunctionsではなくCloud Runを使う場面があり、重宝しました。

2020年12月現在、AWS Lambdaでもコンテナに対応したそうですので試してみたいですが、外部公開のAPIまでとなるとまだAPI Gatewayが必要なので、どうしてもコストがかかります。その点、Cloud Runの無料枠は外部APIさえ作れてしまいますので、0円アプリを作るのに良いですね。

17
18
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?