LoginSignup
4
1

FastAPIでLINEBotを作成しTerraformでGCPのCloud Runに爆速デプロイする

Last updated at Posted at 2024-02-13

概要

最近、ハッカソンなどでLINEBotの作成することが増えてきました。

そこで、開発を円滑に進めるために、Pythonで作成したLINE BotのサーバをGoogle Cloud Platform (GCP) にTerraformを使用してデプロイするテンプレートを作成しました。

この記事では、Pythonで作成した「おうむ返し」機能を持つLINEBotをGCPのCloud Runにデプロイし、LINE Botが実際に動作するまでの手順を説明します。

さらに、GithubとGCPを連携させてCI/CD環境を構築します。これにより、Githubのmainブランチが更新されると、Cloud Runに自動で最新版がデプロイされるようなCloud Build Triggerを設定します。

本手順実行後の最終的な構成は以下の通りです。

スクリーンショット 2024-02-12 22.08.04.png

この記事で実施すること

  • Fast APIを使用してLINE Botを構築
  • Terraformを使用してCloud Runにデプロイ

事前準備

本記事は、以下のリポジトリをベースに構築していく。

ローカルにリポジトリをクローンしておく。

開発用のLINEBotの作成とトークンの取得

開発用のLINEBotを作成するために、まずはLINE Developerコンソールにログインする。

ログイン後、下記のドキュメントに従い「チャンネルアクセストークンを発行する」まで進める。

チャンネルアクセストークンは「長期のチャンネルアクセストークン」を選択し発行する。

発行した2つのトークンは、後の工程で利用するので控えておく。

  • チャネルシークレット
  • チャネルアクセストークン(長期)

デフォルトの「あいさつメッセージ」と「応答メッセージ」を無効

デフォルトの場合、友達追加時の「挨拶メッセージ」と、メッセージを入力時の「応答メッセージ」が有効になっているため、これらを無効にする

「チャンネルアクセストークン」を取得した画面と同じ画面にある「LINE公式アカウント機能」の「編集」ボタンから「応答設定」画面に遷移し、これら2つの機能を無効化する。

スクリーンショット 2024-02-12 20.42.18.png

以下の状態になっていれば、無効化が完了している。「Webhook」は今回作成するLINEBotが利用するtあめ、有効にしておく必要がある。

スクリーンショット 2024-02-12 20.42.05.png

Githubのシークレットトークンの取得

CI/CDの設定のためにGithubのトークンが必要なため、以下のリンクからトークンを取得する。

.envの作成

クローンしたソースコードの.env.sampleを参考に、.envファイルを作成する。先ほど取得したLINEとGithubのシークレットを、.envの各環境変数に設定していく。

.env
# 下記のURLにアクセスし、GITHUBのトークンを取得してください
# https://github.com/settings/tokens
GITHUB_TOKEN=

# 下記のURLにアクセスし、Messaging APIの利用を開始してください
# https://developers.line.biz/console/
LINE_CHANNEL_SECRET=
LINE_CHANNEL_ACCESS_TOKEN=

実装

Fast APIサーバのローカルの動作確認から、Cloud Runへのデプロイまでを実施する。

Fast APIでLINE Botサーバの構築

まず、poetryを利用して仮想環境と必要なライブラリをインストールする。

poetry install

poetryがインストールされていない場合は、以下のリンクを参考にインストールする。

次に、環境変数を更新する。

source .env

そして、Fast APIサーバを起動する。

poetry run uvicorn app.main:app --host 0.0.0.0 --port 8080

以下のURLにアクアセスしSwaggerのAPIドキュメントが表示されれば、正常に起動できている。

app/routes/line_bot_callback_route.pyにはおうむ返しの処理が記述してある。自分が作りたい機能がある場合は、このファイルを修正する。

app/routes/line_bot_callback_route.py
from fastapi import APIRouter, BackgroundTasks, Header, Request
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage
from starlette.exceptions import HTTPException

from app import config


line_bot_callback_router = APIRouter(prefix="", tags=["line_bot"])
line_bot_api = LineBotApi(config.LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(config.LINE_CHANNEL_SECRET)


@line_bot_callback_router.post("/callback")
async def callback(
    request: Request,
    background_tasks: BackgroundTasks,
    x_line_signature=Header(None),
):
    """Line Bot用のエンドポイント"""
    body = await request.body()

    try:
        background_tasks.add_task(
            handler.handle, body.decode("utf-8"), x_line_signature
        )
    except InvalidSignatureError:
        raise HTTPException(status_code=400, detail="Invalid signature")

    return "ok"


@handler.add(MessageEvent)
def handle_message(event):
    if event.type != "message" or event.message.type != "text":
        return
    # 受け取ったメッセージをそのまま返す
    # 処理をカスタムする場合は、ここを編集する。
    message = TextMessage(text=event.message.text)
    line_bot_api.reply_message(event.reply_token, message)

GCP にデプロイ

Fast APIで作成したおうむ返しするLINE BotをGCPに構築する。利用するTerraformはリポジトリのterraform以下にある。

必要パッケージのインストール

Terraformとその前処理を実行するために、terraform(今回はtfenv)とgoogle-cloud-sdkをインストールする。

brew install tfenv
brew install --cask google-cloud-sdk

tfenvは複数のバージョンのTerraformを利用するときに、Terraformのバージョン管理を簡単に行ってくれるツール。

GCPの設定

まず、GCP上に新規でプロジェクトを作成し、プロジェクトIDを取得する。その後、作成したプロジェクトに課金アカウントの紐付けを行う。

課金アカウントの紐付けは、公式ドキュメントを参照。

Terraform実行アカウントをGCPに作成する

プロジェクトの作成と課金アカウントの紐付けが完了したら、Terraformの実行アカウントとサービスアカウントのキーを発行する。

cd terraform
bash - ./init.sh ${プロジェクトID}

実行後、下記のようなOAuthログイン画面が表示される。GCPのプロジェクトIDと紐づいているアカウントを選択し、ログインを行う。

スクリーンショット 2023-05-21 11.06.24.png

OAuthログインが完了しコマンド実行後、terraform/keyの配下にterraform-key.jsonが作成される。

このキーがTerraformを実行する際の認証キーとなる。

`init.sh`の詳細はこちら

init.shはterraformのデプロイユーザを作成し、その認証キーを発行しローカルに保存するスクリプト。

terraform/init.sh
PROJECT_ID=$1

gcloud auth application-default login --disable-quota-project

echo ${PROJECT_ID}
gcloud config set project ${PROJECT_ID}
gcloud iam service-accounts create terraform-account \
  --display-name "Used by Terraform on the local machine"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member serviceAccount:terraform-account@${PROJECT_ID}.iam.gserviceaccount.com \
  --role roles/admin

# Save Service Account json File
gcloud iam service-accounts keys create key/terraform-key.json \
  --iam-account terraform-account@${PROJECT_ID}.iam.gserviceaccount.com

TerraformでGCPのデプロイ

Terraformでデプロイされるサービスは以下の通り。

サービス名 名称 概要
Cloud Run ${Gitのリポジトリ名} FastAPIサーバがデプロイされるサーバ
Cloud Build Trigger ${Gitのリポジトリ名}-trigger Githubのmainブランチの更新を検知し、Build/Cloud Runへのデプロイを行う
Artifact Registry ${Gitのリポジトリ名}/${Gitのリポジトリ名} Cloud Runで起動するアプリケーションのDockerイメージ
Secret Manager LINE_CHANNEL_SECRET,LINE_CHANNEL_ACCESS_TOKEN LINEBotで利用するLINE_CHANNEL_SECRET,LINE_CHANNEL_ACCESS_TOKEN。認証情報なので環境変数ではなく、Secret Managerとして保存する

初回実行時はTerraformの初期化処理を行う

terraform init

その後、リソースをデプロイする。実行後プロジェクトIdの入力が必要になるため、前の手順で取得したプロジェクトIDを入力する

$ terraform apply
var.project_id
  gcp project id

  Enter a value: ${プロジェクトID}

10分以上必要なので、待機しておく。

実行完了後Cloud Runのコンソールに遷移し、サーバが起動していることを確認する。コンソールの詳細ページからURLを取得し、URLの末尾に/docsを付与してSwaggerにアクセスする

スクリーンショット 2024-02-12 19.00.59.png

ローカルで確認した時と同様に、Swaggerの画面が表示されたら、サーバの起動はOK

スクリーンショット 2024-02-12 20.12.46.png

LINEのWebhook URL設定

LINE Developerコンソールに戻り、「事前準備」で作成したLINEBotのWebhook URLに、Cloud Runのエンドポイントを設定する。

エンドポイントは、Cloud Runに表示されていたURLに/callbackを付与したものとなる。

スクリーンショット 2024-02-12 20.19.02.png

設定が完了したら、「検証」ボタンをクリックして接続を確認する。「成功」が表示されれば、LINE BotとCloud RunのAPIは正しく接続されている。

スクリーンショット 2024-02-12 20.19.36.png

動作確認

LINE DeveloperコンソールのQRコードをスキャンして友達追加する。その後、トーク画面で任意のメッセージを送信する。

スクリーンショット 2024-02-12 20.46.40.png

送信したメッセージと同じ内容が返ってきたら、正常にLINE Botが構築されている。

おわりに

利用したソースコードは以下の Github で公開しています

4
1
0

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
4
1