Share
Embed
マルチクラウド対応サービスでCloudflareを使った話
2025/9/3に開催された、cloudflare meetup fukuoka vol.3での登壇資料です。
https://cfm-cts.connpass.com/event/361031/
マルチクラウド対応で作成した個人プロダクトを例にとって設計の重要性について触れつつ、実際にcloudflareに対応させる中で遭遇したいくつかのTIPSについて述べています。
Ken'ichirou Kimura
September 15, 2025
Transcript
26 slides
-
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. マルチクラウド対応サービスで Cloudflareを使った話
木村健一郎 2025年9月3日 Cloudflare Meetup Fukuoka Vol.3 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 名前 :木村健一郎(しょーちゃん)
所属 :株式会社オルターブース SORACOM UG九州 JAWS-UG福岡 娘ちゃんのパパ(8歳1ヶ月) お仕事:IoT番長 受賞歴:SORACOM MVC 2021,2023 AWS Samurai 2019 APJ Commnity Award 2023(Ownership) 好きなAzureサービス :IoT Hub、Functions、Cosmos DB 好きなAWSサービス :Lambda、App Runner、IoT Core SNS : @show_m001 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 最近の口癖 •
設計の知識が重要 • AIが正しいコードを書いてくれない?それは設計してないからだよ • ちゃんと設計しないから意図がAIや人に伝わらないんだよ • 設計の上で詳細実装依存部分はちゃんと切り分けようね ・・みたいなことを最近よく言ってます。 今日はその流れでマルチクラウド対応した個人プロダクトの、 Cloudflare対応についてお話しします。 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. どういうもの? •
3月にサービス終了した、LINE Notifyの代替サービス • LINE Messaging APIを使ったボットプログラム • https://{ボットのEndpoint}/notify というURLにこれまでの LINE Notifyと同じように送信すると、ボットが参加してるグ ループまたはボットの友達全員に通知する • LINE Notifyの入力形式は一通り実装してるはずなので、画像を アップロードして送ることも可能 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 特徴 •
マルチクラウド対応(AWS/Azure/Cloudflare) • レイヤードアーキテクチャで作ってるから他のクラウドサービス版を 作るのも容易 • IaCも準備してるのでデプロイも楽ちん • AWSならcdk deploy一発 • Azureなら「Deploy to Azure」ボタンとGitHub Actionsで • Cloudflareならterraformとwranglerで • ライセンスはMIT -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. アーキテクチャ概要(Lambda) Lambda
handler IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler ハンドラーは実行環境に対するエンドポイントの提供と、各サービスのDIのみ行う -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler ビジネスロジックは、純粋なロジックのみで特定の環境に依存しない -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler LINE Messaging APIとやり取りするサービスクラスはLINE Messaging APIにのみ依存する -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler ビジネスロジックは抽象化したインターフェースを介して環境に依存する処理を呼び出す -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler 環境に依存する処理は各サービスクラスがインターフェースを実装する -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler つまり、別の環境で動かす場合は環境依存の部分だけを修正(別途実装/DI)すればよく、 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Lambda handler
IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp S3ImageStorage JimpImageConvert er LineService DynamoGroupRep ository use use use IHttpRequestHandler LambdaHttpReque stHandler コアロジックには一切の変更が不要 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Microsoft Azureの場合
Functions HttpTrigger handler IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp BlobImageStorage JimpImageConvert er LineService TableStorageGroup Repository use use use IHttpRequestHandler FunctionsHttpRequ estHandler -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 本プロダクトに必要な物 •
JSが動いてHTTPでトリガーできること • Cloudflare workersでいけそう • 画像を保存し、HTTPで公開する機能があること • R2がある • LINEグループの情報を保存するため、Key valueとして使える データストアがあること • KVがある Cloudflareでいけるやん! -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 本プロダクトに必要な物 •
JSが動いてHTTPでトリガーできること • Cloudflare workersがある • 画像を保存し、HTTPで公開する機能があること • R2がある • LINEグループの情報を保存するため、Key valueとして使える データストアがあること • Workers KVがある Cloudflareでいけるやん! -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Cloudflareの場合 Cloudflare
handler IImageConverter IImageStorage IGroupRepository LineNotifyMesse ngerApp R2ImageStorage JimpImageConvert er LineService KVGroupRepository use use use IHttpRequestHandler CloudflareHttpRequ estHandler -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 比較表 機能
AWS Lambda Microsoft Azure Cloudflare HTTPトリガーでJSを実 行 AWS Lambda Azure Functions Cloudflare Workers 画像を保存 Amazon S3 Azure Blob Storage R2 グループ情報のデータ ストア(key value) Amazon DynamoDB Azure Table Storage Workers KV Infrastructure as Code CDK Bicep Terraform -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. Infrastructure as
Code/CI/CD • IaCにterraformを使用 • Apiキーとアカウントidを設定してterraformでKVの名前空間とR2のバ ケットを作成 • デプロイはwranglerを使用 • GitHub Actionsでは、terraformが出力したKVの名前空間idとR2のバ ケット名を環境変数で渡してテンプレートファイルから wrangler.tomlを作成 • wrangler typesコマンドでビルドに必要な型定義を出力させる • wrangler buildコマンドでビルド • wrangler deployコマンドでデプロイ -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. wrangler typesについて
• TypeScriptをビルドするための型情報をソースコードから生成 してくれる • Pure JSなら不要(多分) export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const lineChannelAccessToken = env.LINE_CHANNEL_ACCESS_TOKEN; const kvNamespace: KVNamespace<string> = env.GROUPS ….. } ハンドラーがこんな感じで設定を受け取るが、Envの型定義が不明なため、このままだとTypeScript のトランスパイルで怒られる -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. wrangler typesについて
• そこで使うのがwrangler typesコマンド declare namespace Cloudflare { interface Env { GROUPS: KVNamespace; LINE_CHANNEL_ACCESS_TOKEN: string; AUTHORIZATION_TOKEN: string; SEND_MODE: string; IMAGES: R2Bucket; } } interface Env extends Cloudflare.Env {} こんな感じの型定義ファイルを作ってくれるので、tsconfig.jsonでそれを参照するようにする -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. 実際のコーディング •
これだけ準備すると、Copilot Chatに「このインターフェース をCloudflare R2で実装して」「このインターフェースを Cloudflare Workers KVで実装して」の一言でだいたいいける • ハンドラーも「他の実装を参考にCloudflareに合わせて」くら いでいける • つまり、設計超重要 -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. workersの制限について •
S3/Blob Storageの処理に合わせて「画像をアップロードした ら念の為に自分自身のURL叩いて取得できるか確認」という処 理を入れてた • 画像の取得を https://{workersのURL}/images でworkersから返すよ うにしている • Cloudflare workersだとエラーになる • workersからworkersを取得できないという制限があるから • 再帰呼び出しでの無限ループを避けるためと思われる • https://developers.cloudflare.com/workers/platform/limits/#work er-to-worker-subrequests • If you attempt to use global fetch() to make a subrequest to another Worker on your account that runs on the same zone, without service bindings, the request will fail. -
Copyright © 2015-2025 ALTERBOOTH inc. All Rights Reserved. まとめ •
LINE Notify互換のボットプログラム作りました • レイヤードアーキテクチャでできるだけSOLIDに沿うように作ってい ます • その結果、マルチクラウド(Azure/AWS/Cloudflare)に対応してるの で好きな環境で動かせます • ちゃんと設計したら環境依存部分はAIが上手に書いてくれる • みなさんぜひ設計論を勉強しよう • Cloudflare WorkersをTypeScriptで書くときにはwrangler typesというコマンドがある • WorkersからWorkersはfetch呼べない • Service Bindingsを使う