概要
最近、ハッカソンなどで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を設定します。
本手順実行後の最終的な構成は以下の通りです。
この記事で実施すること
- Fast APIを使用してLINE Botを構築
- Terraformを使用してCloud Runにデプロイ
事前準備
本記事は、以下のリポジトリをベースに構築していく。
ローカルにリポジトリをクローンしておく。
開発用のLINEBotの作成とトークンの取得
開発用のLINEBotを作成するために、まずはLINE Developerコンソールにログインする。
ログイン後、下記のドキュメントに従い「チャンネルアクセストークンを発行する」まで進める。
チャンネルアクセストークンは「長期のチャンネルアクセストークン」を選択し発行する。
発行した2つのトークンは、後の工程で利用するので控えておく。
- チャネルシークレット
- チャネルアクセストークン(長期)
デフォルトの「あいさつメッセージ」と「応答メッセージ」を無効
デフォルトの場合、友達追加時の「挨拶メッセージ」と、メッセージを入力時の「応答メッセージ」が有効になっているため、これらを無効にする
「チャンネルアクセストークン」を取得した画面と同じ画面にある「LINE公式アカウント機能」の「編集」ボタンから「応答設定」画面に遷移し、これら2つの機能を無効化する。
以下の状態になっていれば、無効化が完了している。「Webhook」は今回作成するLINEBotが利用するtあめ、有効にしておく必要がある。
Githubのシークレットトークンの取得
CI/CDの設定のためにGithubのトークンが必要なため、以下のリンクからトークンを取得する。
.env
の作成
クローンしたソースコードの.env.sample
を参考に、.env
ファイルを作成する。先ほど取得したLINEとGithubのシークレットを、.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
にはおうむ返しの処理が記述してある。自分が作りたい機能がある場合は、このファイルを修正する。
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と紐づいているアカウントを選択し、ログインを行う。
OAuth
ログインが完了しコマンド実行後、terraform/key
の配下にterraform-key.json
が作成される。
このキーがTerraformを実行する際の認証キーとなる。
`init.sh`の詳細はこちら
init.sh
はterraformのデプロイユーザを作成し、その認証キーを発行しローカルに保存するスクリプト。
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にアクセスする
ローカルで確認した時と同様に、Swaggerの画面が表示されたら、サーバの起動はOK
LINEのWebhook URL設定
LINE Developerコンソールに戻り、「事前準備」で作成したLINEBotのWebhook URLに、Cloud Runのエンドポイントを設定する。
エンドポイントは、Cloud Runに表示されていたURLに/callback
を付与したものとなる。
設定が完了したら、「検証」ボタンをクリックして接続を確認する。「成功」が表示されれば、LINE BotとCloud RunのAPIは正しく接続されている。
動作確認
LINE DeveloperコンソールのQRコードをスキャンして友達追加する。その後、トーク画面で任意のメッセージを送信する。
送信したメッセージと同じ内容が返ってきたら、正常にLINE Botが構築されている。
おわりに
利用したソースコードは以下の Github で公開しています