SAM CLI + DynamoDB Local 環境構築手順メモ


* SAM  CLIとDynamo DB Localを使用してローカル環境でサーバーレスアプリを構築する手順についてメモする。

## 前提条件

* Docker、docker-composeインストール済みであること。

* dynamodb-admin(DynamoDB GUIツール)インストール済みであること。[インストール手順](https://qiita.com/KWS_0901/items/5768bafe84cf86766645)

* SAM CLIインストール済みであること。

* ディレクトリ構成

  ```shell
  local_app	-	dynamodb	--	docker-compose.yml
  			|				|_	docker	-	dynamodb
  			|_	sam-app				
  ```

## 構築手順

### DynamoDB Local準備

1. `docker-compose.yml`準備

   ```yaml
   version: '3.8'
   services:
     dynamodb-local:
       command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
       image: "amazon/dynamodb-local:latest"
       container_name: dynamodb-local
       ports:
         - "8000:8000"
       volumes:
         - "./docker/dynamodb:/home/dynamodblocal/data"
       working_dir: /home/dynamodblocal
       networks:
         - lambda-local
   networks:
     lambda-local:
       external: true
   ```

**2.Docker network 作成＋コンテナ起動**

   ```shell
   docker network create lambda-local
   docker-compose up
   ```

   ※localhost:8000でコンテナが起動する。

**3.dynamodb-admin(`http://localhost:8001`)にアクセス**

**4.テスト用テーブル`test-table`作成**
   ※テーブル設定は下記の通り。

   ```json
   {
     "AttributeDefinitions": [
       {
         "AttributeName": "name",
         "AttributeType": "S"
       },
       {
         "AttributeName": "date",
         "AttributeType": "S"
       }
     ],
     "TableName": "test-table",
     "KeySchema": [
       {
         "AttributeName": "name",
         "KeyType": "HASH"
       },
       {
         "AttributeName": "date",
         "KeyType": "RANGE"
       }
     ],
     "TableStatus": "ACTIVE",
     "CreationDateTime": "2022-01-16T05:43:16.767Z",
     "ProvisionedThroughput": {
       "LastIncreaseDateTime": "1970-01-01T00:00:00.000Z",
       "LastDecreaseDateTime": "1970-01-01T00:00:00.000Z",
       "NumberOfDecreasesToday": 0,
       "ReadCapacityUnits": 3,
       "WriteCapacityUnits": 3
     },
     "TableSizeBytes": 116,
     "ItemCount": 3,
     "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/test-table"
   }
   ```

   

### SAMプロジェクト準備

**1.SAMプロジェクト作成**

local_appディレクトリ内で次のコマンドを実行。

```shell
sam init --runtime python3.8
```
※HelloworldFunction利用。その他もデフォルト設定で作成。

**2.各種設定、コード変更**

* `app.py`

  DynamoDBテーブル`test-table`に`name`、`date`を登録する。

```python
import json
import boto3
import string
import random
from datetime import datetime


def lambda_handler(event, context):
    # DynamoDB接続設定
    session = boto3.session.Session()
    region = session.region_name
    dynamodb = boto3.resource('dynamodb', region_name = region, endpoint_url = "http://dynamodb-local:8000")
    # テーブルを取得
    table = dynamodb.Table('test-table')
    # name(文字数5の英数字文字列)
    dat = string.digits + string.ascii_lowercase + string.ascii_uppercase
    name = ''.join([random.choice(dat) for i in range(5)])
    # 日時
    date = datetime.utcnow().isoformat()
    # 登録アイテム
    item = {'name': name, 'date': date}
    # テーブル登録
    table.put_item(
        Item=item
    )
    return {
        "statusCode": 200,
        "body": json.dumps(item),
    }

```

* `requirements.txt`

  ※`boto3`追加

  ```txt
  requests
  boto3
  ```

* `template.yml`

  ※Pathを`/item`、Methodを`post`に変更

  ```yaml
  ~省略~
        Events:
          HelloWorld:
            Type: Api 
            Properties:
              Path: /item
              Method: post
  ```

**3.API起動**

```shell
sam local start-api --docker-network lambda-local
```



## 動作確認

* APIリクエスト

  ```http
  POST /item HTTP/1.1
  Host: localhost:3000
  Content-Type: application/json
  Content-Length: 2
  
  {}
  ```

* APIレスポンス

  ```json
  {
      "name": "d4jlG",
      "date": "2022-01-16T06:00:45.853215"
  }
  ```

* dynamodb-adminからテーブル内容確認
![dynamo_api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/844b1c71-a2d4-d017-1fc8-51a90fefc31e.png)