Serverless 構成で lambda ローカルデバッグ用に AWS SAM CLI を使用する方法を調査したものを備忘録として残しておく
環境
- Infrastructure:
- AWS
- lambda: nodejs(20.X)
- Secret Manager
- RDS: PostgreSQL
- AWS API Gateway
- API Key あり
- AWS
- AWS SAM CLI
- Docker Compose
- API 仕様書
- OpenAPI 3.0
AWS SAM 環境について
必要なファイルの内、重要な部分のみ記載
[template.yaml]
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: nodejs20.x
Timeout: 5
MemorySize: 256
Environment:
Variables:
DB_NAME: test_db
DB_HOST: host.docker.internal
DB_USER: postgres
DB_PORT: 5432
SECRET_NAME: local-secret
IS_LOCAL: true
NODE_ENV: local
AWS_ENDPOINT_SECRETS_MANAGER: http://host.docker.internal:4566
AWS_REGION: ap-northeast-1
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_SDK_LOAD_CONFIG: 1
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1
Resources:
# API Gateway
LocalApi:
Type: AWS::Serverless::Api
Properties:
StageName: local
Cors:
AllowMethods: "'*'"
AllowHeaders: "'*'"
AllowOrigin: "'*'"
Auth:
ApiKeyRequired: true
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: ./docs/open_api.yml # Parameterized OpenAPI 3.0 file
# Lambda Function
GetUserDetailFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: functions/getUserDetail/
Handler: index.handler
Layers:
- !Ref PgLayer
Events:
ApiEvent:
Type: Api
Properties:
RestApiId: !Ref LocalApi
Path: /users/{userId}
Method: GET
PgLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: pg-layer
Description: PostgreSQL client for Node.js
ContentUri: layers/pg-layer.zip
CompatibleRuntimes:
- nodejs20.x
[docker-compose.yml]
services:
postgres:
image: postgres:13
container_name: test-postgres
environment:
POSTGRES_DB: test_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
localstack:
image: localstack/localstack:latest
ports:
- "4566:4566" # LocalStack Gateway
- "4510-4559:4510-4559" # External services port range
environment:
- DEBUG=1
- DOCKER_HOST=unix:///var/run/docker.sock
- LAMBDA_EXECUTOR=docker
- PERSISTENCE=1
- SERVICES=secretsmanager
- DEFAULT_REGION=ap-northeast-1
- AWS_DEFAULT_REGION=ap-northeast-1
- AWS_ACCESS_KEY_ID=test
- AWS_SECRET_ACCESS_KEY=test
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
- "./scripts/init-localstack.sh:/etc/localstack/init/ready.d/init-localstack.sh"
- "./scripts/local-secret.json:/etc/localstack/local-secret.json"
volumes:
postgres_data:
[init-localstack.sh]
#!/bin/bash
# LocalStackのエンドポイント
ENDPOINT="http://localhost:4566"
# シークレット値を外部ファイルから読み込む
SECRET_STRING=$(cat /etc/localstack/local-secret.json)
# シークレットの作成
aws --endpoint-url=$ENDPOINT secretsmanager create-secret \
--name local-secret \
--description "Local development secret" \
--secret-string "$SECRET_STRING" \
--region ap-northeast-1
echo "LocalStack secrets initialized"
[local-secret.json]
{
"password": "postgres"
}
[create-pg-layer.sh]
#!/bin/bash
set -e
LAYER_DIR="layers/pg-layer"
ZIP_FILE="layers/pg-layer.zip"
mkdir -p "$LAYER_DIR/nodejs"
cp layers/package.json "$LAYER_DIR/nodejs/package.json"
cd "$LAYER_DIR/nodejs"
npm install --production
cd ../../..
rm -f "$ZIP_FILE"
cd "$LAYER_DIR"
zip -r "../../$ZIP_FILE" .
cd ../../
echo "pg-layer の作成が完了しました: $ZIP_FILE"
rm -rf "$LAYER_DIR"
使用方法
実施手順
$ docker-compose up -d
- Copy the DB in the Dev environment
- If the Layer is updated, do the following
$ ./scripts/create-pg-layer.sh
$ sam local start-api
シークレットマネージャーに値が追加された場合
ローカルデバッグでは localstack を使用する
scripts/local-secret.json
を編集して、値を追加するdocker-compose down
&docker-compose up -d
- localstack の初期化スクリプトが実行され、シークレットマネージャーに値が追加される
- localstack のシークレットマネージャーに値が追加されたことを確認する
$ AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test aws --endpoint-url=http://localhost:4566 --region ap-northeast-1 secretsmanager get-secret-value --secret-id local-secret