クレカ不要!Lambda × Go を無料でスケジューリングしよう! a. k. a. Netlify Functions
はじめに
貧乏エンジニアリングシリーズ最新作です!
どこか Web ホスティングするのに、なにかサービスないかなあって探していたら、Netlify というサービスを見つけました。
こちらのサービスも以前 Vercel で紹介したように無料で Go サーバーを構築することができたので紹介します。
ただ、サーバーを構築するだけだったら公式ドキュメントを参照すれば簡単にできたので実装を少し工夫してスケジュールで動かしてみます。
Netlify とは
公式サイトによるとフレームワークに依存しない「持続可能な Web アーキテクチャ」と説明されています。
あらゆる Web フロントエンドフレームワークに対応しています。
Netlify はこれだけでなくサーバレス関数も提供しています。
サーバレス関数には TypeScript, JavaScript そして Go が対応しています。
準備 & version
Netlify アカウントを作成します。
以下のリンクにアクセスして作成できます。
私は GitHub アカウントにてサインアップしました。
各種操作を行うために Netlify CLI をインストールします。
node --version
v22.11.0
npm --version
11.1.0
npm
にてインストールします。
npm install netlify-cli -g
netlify --version
netlify-cli/19.0.0 darwin-arm64 node-v22.11.0
プロジェクトを開始するために Netlify にログインしておきます。
netlify login
開発のために Go をインストールしておきます。
go version
go version go1.24.0 darwin/arm64
実装
Functions
Neflify は AWS Lambda と互換性のあるサーバーレス関数にて動作します。
(というかたぶん Lambda で動いています。)
ディレクトリ構成や実装については下記のページをご参照ください。
公式ドキュメントのサンプルコードは Lambda の Request と Response を扱う実装になっています。
このままでもよいですが、実装しやすいように net/http
で実装できるようにします。
「します。」といっても @fujiwara さんが作成されている ridge
ライブラリを活用するだけです。
package main
import (
"net/http"
"github.com/aws/aws-lambda-go/lambdacontext"
"github.com/fujiwara/ridge"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ctx, _ := lambdacontext.FromContext(r.Context())
w.Write([]byte(ctx.AwsRequestID))
})
ridge.Run(":8080", "/", mux)
}
Scheduled Functions
スケジュールで動かすために Scheduled Functions を利用します。
ただし、こちらは TypeScript or JavaScript でしか実装できません。
実装をシンプルにするために以下のようにして Fetch API にて先ほど実装した Functions を呼び出すだけにしています。
export default async (_) => {
await fetch(process.env.URL + '/.netlify/functions/<function>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({}),
})
}
※ Functions のエンドポイントは環境変数から取得できます。[1]
※ Functions のパスは /.netlify/functions/<function>
となります。
スケジュールは netlify.toml
にて設定します。
[functions."cron"]
schedule = "@hourly"
※ ファイル名に合わせて functions.<>
を設定します。今回は cron.mjs
というファイル名なので functions."cron"
となっています。
※ @hourly
は1時間ごとに起動する 0 * * * *
と同等です。
デプロイ
最終的にディレクトリは以下のようになっています。
.
├── go.mod
├── go.sum
├── netlify
│ └── functions // Functions を配置するディレクトリ
│ ├── cron.mjs // スケジュールにて起動する関数
│ └── job // API 名
│ └── main.go // API にて起動する関数
└── netlify.toml // cron の設定ファイル
準備ができたら Netlify CLI にてデプロイします。
❯ netlify deploy --prod
This folder isn't linked to a site yet
? What would you like to do? + Create & configure a new site
? Team: otakakot
? Site name (leave blank for a random name; you can change it later): <project>
Site Created
Admin URL: https://app.netlify.com/sites/<accouht>
URL: https://<project>.netlify.app
Site ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Linked to <project>
Please provide a publish directory (e.g. "public" or "dist" or "."):
? Publish directory YOUR_BASE_DIRECTORY
Deploy path: YOUR_BASE_DIRECTORY
Functions path: YOUR_BASE_DIRECTORY/netlify/functions
Configuration path: YOUR_BASE_DIRECTORY/netlify.toml
Deploying to main site URL...
⠋ Uploading blobs to deploy store...
Netlify Build
────────────────────────────────────────────────────────────────
❯ Version
@netlify/build 29.58.10
❯ Flags
deployId: xxxxxxxxxxxxxxxxxxxxxxx
open: false
prod: true
prodIfUnlocked: false
skipFunctionsCache: false
❯ Current directory
YOUR_BASE_DIRECTORY
❯ Config file
YOUR_BASE_DIRECTORY/netlify.toml
❯ Context
✔ Finished uploading blobs to deploy store
✔ No cached functions were found
✔ Finished hashing 5 files and 2 functions
✔ CDN requesting 5 files and 2 functions
✔ Finished uploading 7 assets
✔ Deploy is live!
Build logs: https://app.netlify.com/sites/<account>/deploys/xxxxxxxxxxxxxxxxxxxxxxx
Function logs: https://app.netlify.com/sites/<account>/logs/functions
Edge function Logs: https://app.netlify.com/sites/<account>/logs/edge-functions
Unique deploy URL: https://xxxxxxxxxxxxxxxxxxxxxxxx--<account>.netlify.app
Website URL: https://<project>.netlify.app
動作確認
デプロイし払い出されたエンドポイント + Functions のパスにて動作確認にて実行できます。
curl https://<project>.netlify.app/.netlify/functions/job
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
また、設定された時間になるとスケジュールにて関数が起動します。
Mar 2, xx:00:19 PM: cde4ea92 Duration: 530.33 ms Memory Usage: 97 MB Init Duration: 317.65 ms
この様子は Function logs にて確認できます。
ほかにも Netlify CLI はローカル環境での動作確認もサポートされています。
❯ netlify functions:serve
◈ Ignored shared env var: API_KEY (defined in site settings)
◈ Ignored general context env var: LANG (defined in process)
┌─────────────────────────────────────────────────┐
│ │
│ ◈ Server now ready on http://localhost:9999 │
│ │
└─────────────────────────────────────────────────┘
◈ Loaded function cron
◈ Loaded function job
おわりに
Cloudflare Workers, Vercel Functions と並ぶくらい Go が使いやすい無料のデプロイ環境を見つけました。
今回実装したコードは以下に置いておきます。
Discussion