カテゴリー: Server

LocalStackのLambdaをホットリロードさせる

はじめに

前回に引き続きAWS Lambdaについて取り扱っていきます。今回はLocakStackでホットリロードさせるための設定について紹介します。

全体の流れ

まず初めに、どのようにホットリロードを実現するかについて簡単に紹介します。

大まかな流れは以下のとおりです。

  • コードの変更を検知する(Watchman)
  • 実行ファイルををビルドして、Lambdaにdeployする

それぞれについて、もう少し深掘りします。

コードの変更を検知する

コードの変更の検知にはWatchmanを用います。

Watchmanの機能の1つとして、ファイルを監視しファイルが変更されたときにアクションをトリガーすることができます。

インストール方法については割愛しますので、適宜公式ドキュメントを確認の上、予めインストールしてください。

ファイルをビルドしてdeployする

実行ファイルのdeployについては、AWS CLIの update-function-code APIで行います。

ホットリロードを実現する

それでは、前回のコードをホットリロードできるように改修します。

deployスクリプトを作成する

前回のdeployスクリプトでは、Lambda関数を一度削除してから再度作り直していました。今回はSQS周りの設定などは使い回せるように、実行ファイルのみアップデートするdeployスクリプトを新たに作成します(既存のdeployスクリプトは初回だけ実行するため、lambda_create.shにリネームしておきます)。

新しいdeployスクリプトは以下のとおりです。

#!/usr/bin/env bash

# intel mac用
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o main ./get_message/main.go
zip main.zip main

# Lambdaの設定
aws lambda update-function-code --function-name example-sqs-consumer \
  --zip-file fileb://main.zip --endpoint-url http://localhost:4566 > /dev/null 2>&1

# 後始末
rm main main.zip

get_message/main.go をビルドしてZIP化し、 update-function-code でZIPをアップロードしています。

Watchmanのラッパースクリプトを作成する

つぎに、Watchmanのラッパースクリプトを作成します。

このスクリプトでは、 get_message ディレクトリを監視対象として、更新があった場合に lambda_deploy.sh を実行します。

スクリプトは以下のとおりです(こちらをほぼそのまま使用)。

#!/bin/bash

trap "watchman watch-del $(pwd)" EXIT

folder=$(pwd)/get_message
echo "watching folder $folder for changes"

while watchman-wait $folder; do
  bash -c "./lambda_deploy.sh"
  watchman watch-del $folder
done

get_message ディレクトリのファイルに変更があった場合、 lambda_deploy.sh が実行され、Lambdaが更新されます。

実際に動かしてみる

前回と同様に、LocakStack上にLambdaをdeployして実行すると、コンテナ内に以下のようなログが出力されます。

2023-10-14 03:07:20 localstack_main  | 2023-10-13T18:07:20.643 DEBUG --- [   Thread-38] l.s.l.i.version_manager    : > Message Body: hoge
2023-10-14 03:07:20 localstack_main  | 2023-10-13T18:07:20.644 DEBUG --- [   Thread-38] l.s.l.i.version_manager    : > END RequestId: e189eef5-bd31-4354-b19f-56bb13b9206c

そして、先程作成した hot-reload.go を実行した状態で get_message/main.go を変更してみると、Lambdaが更新され、コンテナが削除されます。

2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.264  INFO --- [   asgi_gw_2] localstack.request.aws     : AWS lambda.UpdateFunctionCode => 200
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.267 DEBUG --- [rvice-task_2] l.s.l.i.lambda_models      : Saving code example-sqs-consumer-a0cdebbe-8d1a-45b9-b672-fd7013cd25ce to disk
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.318 DEBUG --- [rvice-task_2] localstack.utils.run       : Executing command: ['unzip', '-o', '-q', '/tmp/tmpcx_w0h27']
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.384 DEBUG --- [rvice-task_2] l.s.l.i.version_manager    : Version preparation of function arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST took 116.54ms
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.384 DEBUG --- [rvice-task_2] l.s.l.i.version_manager    : Changing Lambda arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST (id ef47b014) to active
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.384 DEBUG --- [rvice-task_2] l.s.l.i.event_manager      : Starting event manager arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST id 140064224615376
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.404 DEBUG --- [rvice-task_2] l.s.l.i.event_manager      : Stopping event manager but keep queue arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST id 140064208828688
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.404 DEBUG --- [rvice-task_2] l.s.l.i.event_manager      : Stopping event poller arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST 140064208335968
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.405 DEBUG --- [rvice-task_0] l.s.l.i.version_manager    : Stopping lambda version 'arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST'
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.405 DEBUG --- [rvice-task_1] l.s.l.i.lambda_models      : Final code destruction for example-sqs-consumer-73f63a74-8953-4420-a61d-5a7a8ca417f7
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.407 DEBUG --- [rvice-task_0] l.u.c.docker_sdk_client    : Stopping container: localstack-main-lambda-example-sqs-consumer-e3c71782b7f89a010821a806f8734fa5
2023-10-14 03:11:13 localstack_main  | 2023-10-13T18:11:13.591 DEBUG --- [rvice-task_0] l.u.c.docker_sdk_client    : Removing container: localstack-main-lambda-example-sqs-consumer-e3c71782b7f89a010821a806f8734fa5
2023-10-14 03:11:15 localstack_main  | 2023-10-13T18:11:15.159 DEBUG --- [rvice-task_2] l.s.l.i.event_manager      : Waited for poller thread <FuncThread(lambda-poller-example-sqs-consumer:$LATEST-functhread12402, stopped daemon 140063304312576)>

この状態で再度Lambdaを動かしてみると、このようにログに hot reloaded のメッセージ(fmt.Printlnで出力させた)が表示されるようになっています。

2023-10-14 03:18:04 localstack_main  | 2023-10-13T18:18:04.316 DEBUG --- [   Thread-42] l.s.l.i.version_manager    : > hot reloaded
2023-10-14 03:18:04 localstack_main  | 2023-10-13T18:18:04.316 DEBUG --- [   Thread-42] l.s.l.i.version_manager    : > Message ID: faf97270-d1d1-40e3-b200-56cf1ac5c82a
2023-10-14 03:18:04 localstack_main  | 2023-10-13T18:18:04.316 DEBUG --- [   Thread-42] l.s.l.i.version_manager    : > Message Body: hoge

これで、変更がLambdaに反映されていることが確認できました。

おまけ

おまけとして、Lambdaに実行ファイルではなくコンテナをdeployして実行する方法を紹介します。

やりかたは簡単で、ECRにDockerイメージをアップロードしておき、Lambda関数の作成時に「コンテナイメージ」を選択して、イメージのURIを指定するだけです。

その際、コンテナイメージの下記の項目を上書きすることができます。

  • ENTRYPOINT
  • CMD
  • WORKDIR

ENTRYPOINTとCMDに関してはカンマ区切りで複数の値を指定できます。

おすすめ書籍

   

Hiroki Ono

シェア
執筆者:
Hiroki Ono
タグ: AWS

最近の投稿

フロントエンドで動画デコレーション&レンダリング

はじめに 今回は、以下のように…

4週間 前

Goのクエリビルダー goqu を使ってみる

はじめに 最近携わっているとあ…

1か月 前

【Xcode15】プライバシーマニフェスト対応に備えて

はじめに こんにちは、suzu…

2か月 前

FSMを使った状態管理をGoで実装する

はじめに 一般的なアプリケーシ…

3か月 前