Mac M1で Serverless Framework を使って AWS Lambda をデプロイする
M1 MacのPCで作業するため、Arm64でビルドできる形で作成しました。
Serverless Framework を使って、以下の機能を実装しました。
- DynamoDBのテーブルを作成
- データの取得・更新・削除の機能を持ったLambda関数
- API GatewayからLambda関数を呼び出す
事前準備
準備として、以下のものが必要です。
- Node.js: Serverless Framework を使用するには、Node.js が必要です。
- AWS アカウント: Serverless Framework を使用するには、AWS のアカウントが必要です。
- AWS アクセスキーとシークレットアクセスキー: Serverless Framework から AWS のサービスを呼び出すには、アクセスキーとシークレットアクセスキーが必要です。
- IAMでロールを作成し、アクセスキーとシークレットアクセスキーを控えます。
AWS CLI を設定する環境変数 - コンソール上で以下のコマンドを実行することで環境変数の設定が可能です。
- IAMでロールを作成し、アクセスキーとシークレットアクセスキーを控えます。
export AWS_ACCESS_KEY_ID=xxxxx
export AWS_SECRET_ACCESS_KEY=xxxxx
export AWS_DEFAULT_REGION=ap-northeast-1
- Serverless Framework のインストール
- Serverless Framework を使用するには、まず、Node.js をインストールし、その上で、以下のコマンドを実行して、Serverless Framework をグローバルインストールします。
npm install -g serverless
プロジェクトの作成
Serverless Framework では、プロジェクトを作成するとともに、必要なリソースを自動で構築することができます。以下のコマンドを実行することで、新しいプロジェクトを作成できます。
serverless create --template aws-python3 --path my-project
このコマンドを実行すると、my-project という名前のディレクトリが作成され、その中に、サンプルの AWS Lambda 関数のファイルhandler.pyや、serverlessの設定ファイルserverless.ymlなどが配置されます。
ファイルの編集
作成されたディレクトリ内の設定ファイルserverless.ymlを編集します。
Macのアーキテクチャはarmであるため、設定をしないとビルドができませんでした。
LambdaをDockerで動かす形で記述しました。
Coffee noteというアプリケーションを作成したため、テーブル名や関数名がcoffee_noteとなっています。
- serverless.yml
service: serverless-coffee-note
useDotenv: true
frameworkVersion: "3.26.0"
provider:
name: aws
architecture: arm64 # デフォルトはx86_64
runtime: python3.8
lambdaHashingVersion: 20201221
# you can overwrite defaults here
# stage: dev
region: ap-northeast-1
iam:
role:
statements:
- Effect: "Allow"
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:Query
Resource: "arn:aws:dynamodb:*:*:table/coffee_note"
ecr:
images:
coffee_note:
file: Dockerfile
path: handler/coffee_note
platform: linux/arm64
resources:
Resources:
coffeeNote:
Type: AWS::DynamoDB::Table
Properties:
TableName: coffee_note
AttributeDefinitions:
- AttributeName: user_id
AttributeType: S
- AttributeName: date
AttributeType: N
KeySchema: [
{
KeyType: "HASH",
AttributeName: "user_id",
},
{
KeyType: "RANGE",
AttributeName: "date",
}]
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
functions:
coffeeNote:
image:
name: coffee_note
command: coffee_note.coffee_note_handler
events:
- http:
path: /coffee_note
method: get
integration: lambda-proxy
cors: true
- http:
path: /coffee_note
method: post
integration: lambda-proxy
cors: true
- http:
path: /coffee_note
method: delete
integration: lambda-proxy
cors: true
-
iam: AWS リソースへのアクセス権限を設定しています。
-
ecr: Docker イメージを AWS Elastic Container Registry (ECR) にプッシュするための設定を行うことができます。
-
image: Docker イメージを指定しています。
-
name: には、ECR リポジトリの名前、command には、Docker コンテナ内で実行されるコマンドを指定します。
-
functions: Lambdaの関数の定義を行なっています。
-
events: Lambda 関数をトリガーするイベントを定義しています。
HTTP リクエストによってこの Lambda 関数がAmazon API Gatewayを通してトリガーされます。 -
handler/coffee_note/coffee_note.py
import json
import boto3
from decimal import Decimal
from boto3.dynamodb.conditions import Key, Attr
dynamodb = boto3.resource('dynamodb') ##Dynamodbアクセスのためのオブジェクト取得
table = dynamodb.Table("coffee_note") ##指定テーブルのアクセスオブジェクト取得
def coffee_note_handler(event, context):
# TODO implement
print(event)
if event["body"] :
body = json.loads(event["body"])
if event['httpMethod']=='GET' :
# scanData = table.scan()
user_id = event['queryStringParameters']
response = table.query(
KeyConditionExpression=Key('userId').eq(user_id['user_id'])
)
items=response['Items']
print(items)
return {
'statusCode': 200,
'body': json.dumps(items ,default=decimal_to_int)
}
if event['httpMethod']=='POST' :
putResponse = table.put_item(を設定
Item={
'user_id': body["user_id"],
'memo': body["memo"],
'date': body["date"],
'star': body["star"],
}
)
return {
'statusCode': 200,
'body': json.dumps('Hello from PostLambda!')
}
if event["httpMethod"] == "DELETE":
delResponse = table.delete_item(
Key={
'user_id': body["user_id"],
'date': body["date"],
}
)
return {
'body': json.dumps('Hello from Lambda!'),
'statusCode': 200
}
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
def decimal_to_int(obj):
if isinstance(obj, Decimal):
return int(obj)
- handler/coffee_note/DockerFile
FROM public.ecr.aws/lambda/python:3.8-arm64
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY *.py ./
- handler/coffee_note/requirements.txt
requests
boto3
デプロイ
設定ファイルを編集したら、以下のコマンドを実行することで、プロジェクトをデプロイすることができます。
serverless deploy
Discussion