はじめに

AWS を勉強のために触りたいが、課金が怖くてなかなか試せない。
そういった方向けに、ローカル開発環境でAWSサービスを実行できるのが、LocalStack です。

今回は、LocalStackを使って簡単なAPIをデプロイしてみようと思います。

前提条件

docker(docker compose コマンドを実行できること)を使用できる状態にしておいてください。

下準備

AWS CLIのインストール

$ sudo apt  install awscli

プロファイルの設定

$ aws configure --profile localstack

AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: us-east-1
Default output format [None]: json

LocalStackのclone

$ git clone https://github.com/localstack/localstack.git
$ cd localstack

※私の環境では、エラーになったため、docker-compose.yml に以下を記載した。

environment:
- LAMBDA_DOCKER_NETWORK=host

LocalStackの起動

docker-compose up -d

Lambdaのデプロイ

1. サンプルファイルの準備

Lambda.py

import json

def lambda_handler(event, context):
    return {
        'statusCode': '200',
        'body': json.dumps('Hello LocalStack API'),
        'headers': {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*'
            },
    }

2. zipにする

$ zip lambda.zip lambda.py

3. Lambda作成

$ aws lambda create-function \
  --function-name test-api-lambda \
  --runtime python3.8 \
  --handler lambda.lambda_handler \
  --memory-size 128 \
  --zip-file fileb://lambda.zip \
  --role arn:aws:iam::000000000000:role/lambda-role \
  --profile localstack \
  --region us-east-1 \
  --endpoint-url=http://localhost:4566

以下については、ダミーで問題ありません。

--role arn:aws:iam::000000000000:role/lambda-role

ただし、

--role test

のようにすると、エラーとなるため、以下の形式にする必要があります。

--role arn:aws:iam::xxx:role/xxx

4. Lambdaの確認

$ aws --endpoint-url=http://localhost:4566 lambda list-functions --profile localstack

この時点で Lambdaが作成できているかどうか確認します。

API Gatewayデプロイ

1. APIの作成

$ aws apigateway create-rest-api --name 'Sample API' --endpoint-url=http://localhost:4566

# 結果
{
    "id": "xxx",
    "name": "Sample API",
    "createdDate": "2023-04-25T10:17:35+09:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "disableExecuteApiEndpoint": false
}

2. ルートリソース ID取得

$ aws apigateway get-resources --rest-api-id {api-id} --endpoint-url=http://localhost:4566

# 結果
{
    "items": [
        {
            "id": "xxx",
            "path": "/"
        }
    ]
}

{api-id}1. APIの作成 で取得できるidを使用する

3. 子リソースを追加

$ aws apigateway create-resource --rest-api-id {api-id} \
  --parent-id {parent-id} \
  --path-part sample \
  --endpoint-url=http://localhost:4566

# 結果
{
    "id": "xxx",
    "parentId": "xxx",
    "pathPart": "sample",
    "path": "/sample"
}

{parent-id}2. ID取得 で取得できるidを使用します。

4. GETメソッドを参照できるように設定

$ aws apigateway put-method \
  --rest-api-id {api-id} \
  --resource-id {resource-id} \
  --http-method GET \
  --authorization-type "NONE" \
  --endpoint-url=http://localhost:4566

# 結果
{
    "httpMethod": "GET",
    "authorizationType": "NONE",
    "apiKeyRequired": false
}

{resource-id}3. 子リソースを追加 で取得できるidを使用します。

5. API Gateway と Lambda の設定

$ aws apigateway put-integration \
  --rest-api-id {api-id} \
  --resource-id {resource-id} \
  --http-method GET \
  --type AWS_PROXY \
  --integration-http-method POST \
  --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:test-api-lambda/invocations \
  --passthrough-behavior WHEN_NO_MATCH \
  --endpoint-url=http://localhost:4566

# 結果
{
    "type": "AWS_PROXY",
    "httpMethod": "POST",
    "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:test-api-lambda/invocations",
    "requestParameters": {},
    "passthroughBehavior": "WHEN_NO_MATCH",
    "cacheNamespace": "ui91214dss",
    "cacheKeyParameters": []
}

6. API デプロイ

$ aws apigateway create-deployment \
  --rest-api-id {api-id} \
  --stage-name dev \
  --endpoint-url=http://localhost:4566

# 結果
{
    "id": "xxx",
    "createdDate": "2023-04-25T10:32:39+09:00"
}

実行確認

$ curl http://localhost:4566/restapis/{api-id}/dev/_user_request_/sample

うまくいかない時

APIが作成されているか確認してみてください。

$ aws apigateway get-rest-apis --endpoint-url=http://localhost:4566

$ aws apigateway get-resources --rest-api-id {api-id} --endpoint-url=http://localhost:4566 

LocalStackを使用してみて

メリット

  • 動作確認のたびにAWSにデプロイする手間が省ける
  • 動作確認の都度課金を心配しなくて良い
  • 何かをまず試してみる時に便利

デメリット

  • コンソールで設定ができない(CLIに慣れていないと効率は落ちそう)
  • Community 版(無料)だと使えないサービスもある

参照URL

https://localstack.cloud/company/

https://github.com/localstack/localstack