AWS SAM+DynamoDBのDockerローカル開発環境を作る
概要
AWS で API Gateway、Lambda、DynamoDB を組み合わせた開発を行うために、AWS SAM を用いて開発環境を構築してみます。
今回は DynamoDB を組み合わせてみますが、AWS SAM による、基本的な API Gateway、Lambda での環境構築および操作方法は、以下を参考にしてみてください。
また、ローカル DynamoDB 単体の構築方法は以下を参考にしてみてください。
前提
以下の内容は、インストール済みの前提とします。
- AWS CLI
- AWS SAM CLI
- Docker
構成
最終的に作成する構成は以下の通りとします。
.
|-- .gitignore
|-- Dockerfile-awscli
|-- README.md
|-- __tests__
| `-- unit
| `-- handlers
| |-- get-all-items.test.js
| |-- get-by-id.test.js
| `-- put-item.test.js
|-- bin
|-- buildspec.yml
|-- docker-compose.yml
|-- env.json
|-- events
| |-- event-get-all-items.json
| |-- event-get-by-id.json
| `-- event-post-item.json
|-- package.json
|-- src
| `-- handlers
| |-- get-all-items.js
| |-- get-by-id.js
| `-- put-item.js
`-- template.yaml
手順
SAM プロジェクトの作成
SAM プロジェクトを作成します。
今回は、ランタイム環境は、Node.js としています。
sam init --runtime nodejs14.x
対話方式で聞かれるので、以下のように選択していきます。
1 - AWS Quick Start Templates
6 - Serverless API
プロジェクト名を聞かれるので、任意のプロジェクト名(例:sam-dynamodb-sample
)を入力します。
docker network の作成
ローカル DynamoDB と SAM 環境を接続するための、docker network を 1 つ個別に作成しておきます。
docker network create lambda-local
AWS CLI(DynamoDB 直操作用)の Dockerfile 作成
作成したプロジェクトフォルダに移動し、以下のファイルを作成します。
FROM amazon/aws-cli
ENV AWS_ACCESS_KEY_ID=fake_access_key\
AWS_SECRET_ACCESS_KEY=fake_secret_access_key\
DYNAMODB_REGION=ap-northeast-1
WORKDIR /usr/app
ローカル DynamoDB 用の Dockerfile 作成
以下のファイルを作成します。
version: '3'
services:
dynamodb:
image: amazon/dynamodb-local
command: -jar DynamoDBLocal.jar -sharedDb -dbPath . -optimizeDbBeforeStartup
volumes:
- dynamodb:/home/dynamodblocal
ports:
- 8001:8000
networks:
- lambda-local
awscli:
build:
context: .
dockerfile: Dockerfile-awscli
entrypoint: [""]
tty: true
command:
- /bin/sh
volumes:
- ./bin:/usr/app
networks:
- lambda-local
volumes:
dynamodb:
driver: local
bin:
driver: local
networks:
lambda-local:
external: true
※DynamoDB のポートは他の処理と衝突しないよう 8000 番ポート →8001 番ポートにマッピングしています。環境に合わせて設定してください。(8000 番ポートでも問題ないです)
設定のポイントとしては、dynamodb
とawscli
の 2 つのサービスを、 lambda-local
ネットワークに参加させている点と、networks
-lambda-local
-external: true
を設定している点になります。
ローカル DynamoDB にテーブルとテストデータを作成する
SAM から接続確認をするための、テーブルを、ローカル DynamoDB 上に作成しておきます。
コンテナを起動する
docker-compose up -d
AWS CLI 用コンテナ名を確認する
docker ps -a
AWS CLI 用コンテナに入る
docker exec -it [AWS CLI用コンテナ名] /bin/bash
テーブル作成
aws dynamodb \
--region ap-northeast-1 \
--endpoint-url http://dynamodb:8000 \
create-table \
--table-name SampleTable \
--attribute-definitions \
AttributeName=id,AttributeType=S \
--key-schema \
AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
※テーブル名SampleTable
及びパーティションキーid
は、SAM の6 - Serverless API
で使用している名前のため、今回は動作確認しやすいように、それに合わせています。
※結果が表示されたら下までスクロールしてq
で抜けます。
テストデータ追加
aws dynamodb put-item \
--region ap-northeast-1 \
--endpoint-url http://dynamodb:8000 \
--table-name SampleTable \
--item '{
"id": {"S": "123"},
"name": {"S": "Test"}
}'
操作が終わったら、exit
でコンテナから抜けます。
DynamoDBClient の接続情報をローカル接続に対応させる
Lambda ソース内の DynamoDBClient 接続に関して、ローカル環境の場合にローカル DynamoDB を参照するように、以下のように書き換えておきます。
対象ファイル(例)
src/handlers/get-all-items.js
編集前
const docClient = new dynamodb.DocumentClient();
編集後
const docClient = new dynamodb.DocumentClient(
process.env.AWS_SAM_LOCAL
? {
credentials: {
accessKeyId: "fakeMyKeyId",
secretAccessKey: "fakeSecretAccessKey",
},
region: "ap-northeast-1",
endpoint: "http://dynamodb:8000",
}
: {}
);
※SAM Local で実行した場合process.env.AWS_SAM_LOCAL
がtrue
になっています。
SAM ローカルで関数を実行する
以下の関数を実行し、ローカルで関数の動作を確認します。
sam local invoke -e events/event-get-all-items.json --docker-network lambda-local getAllItemsFunction
実行結果
INFO response from: undefined statusCode: 200 body: [{"name":"Test","id":"123"}]
事前に投入したテストデータが出力されれば OK です。
SAM ローカルで API を実行する
続いて、ローカルで API を動かして確認してみます。
sam local start-api --docker-network lambda-local
ブラウザで次の URL にアクセスします。
http://127.0.0.1:3000/
次のレスポンスが返却されれば OK です。
[{ "name": "Test", "id": "123" }]
ローカルでの確認は以上で終了です。
あとは、sam deploy --guided
で実際に AWS 環境にデプロイして確認していけば OK です。
注意点
SAM から DynamoDB テーブルを作成した場合、自動的に次のような名前のテーブルが生成されます。
sam-app-SampleTable-FGDKBGW9SS75
SAM 以外からも参照するテーブルや既存テーブルの場合は、SAM 側からはテーブルを作成しないようにするといった工夫が必要になると思います。
まとめ
APΙ Gateway+Lambda+DynamoDB で API を作成するパターンは多いかと思います。
いずれ、ローカル DynamoDB や docker network を用意しなくても、AWS SAM だけで出来るようになりそうにも思いますが、ローカルで DynamoDB も含めて確認できると便利な場面はいろいろとありそうです。
Discussion