0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS 0円生活!LocalStackで始める貧乏開発入門

Posted at

はじめに

クラウドサービスを活用したサーバーレス開発に興味はあるけれど、AWSの利用料金が気になって一歩踏み出せない…

そんなときは、LocalStackを使ってローカル環境でサーバーレスアーキテクチャを構築する方法をお試しください。

これにより、0円でAWSの主要サービスを模擬し、開発・テストを効率的に行うことができます。

LocalStackとは?

LocalStackは、AWSクラウドの主要サービスをローカル環境でエミュレートできるオープンソースのプラットフォームです。
これを使えば、AWSのインフラに依存せずに開発・テストが可能となり、コストをかけずにサーバーレスアーキテクチャを体験できます。

対応サービスは多岐にわたり、今回はLambda, API Gateway, DynamoDB, S3, SQSを中心に紹介します。

システム構成図

以下の図は、今回のサンプルのLocalStackを利用したサーバーレスアーキテクチャの全体像を示しています。

図1: LocalStackを用いたサーバーレスアーキテクチャの全体図

必要なものを準備しよう

まず、開発を始める前に以下の環境が整っていることを確認しましょう。

  • macOS(Homebrewが利用可能)
  • Python 3.7以上
  • pip(Pythonパッケージ管理ツール)
  • Homebrew(macOS用パッケージマネージャ)
  • AWS CLI(後述でインストールします)

LocalStackのインストールと起動

Homebrewを使ってLocalStack CLIをインストール

ターミナルを開き、以下のコマンドを実行してLocalStack CLIをインストールします。

brew install localstack/tap/localstack-cli

LocalStackをバックグラウンドで起動

インストールが完了したら、次のコマンドでLocalStackをデタッチモード(バックグラウンド)で起動します。

localstack start -d

起動したサービスを確認

正常に起動しているか確認するため、以下のコマンドを実行します。

localstack status services

表示されたサービス一覧に、lambda, apigateway, dynamodb, s3, sqsが含まれていることを確認しましょう。

サービス構成図

LocalStackで利用するサービスの関係を以下の図で確認しましょう。

図2: LocalStack内のサービス間の関係

AWS CLIの設定

LocalStackを操作するために、AWS CLIの設定が必要です。まだインストールしていない場合は、以下のコマンドでインストールします。

brew install awscli

AWS CLIの初期設定

ローカル環境用にAWS CLIを設定します。ダミーのアクセスキーとシークレットキーを使用します。

aws configure

プロンプトに従い、以下のように入力してください。

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

これで、AWS CLIがLocalStackと連携する準備が整いました。

サーバーレスアプリケーションを構築

ここからは、LocalStack上にサーバーレスアーキテクチャの各コンポーネントを構築していきます。

Lambda関数の作成

まず、簡単なLambda関数を作成します。プロジェクト用のディレクトリを作成し、lambda_function.pyというファイルを作成して以下の内容を記述します。

# lambda_function.py
import json
import boto3
import os

def handler(event, context):
    # DynamoDBにデータを追加
    dynamodb = boto3.resource('dynamodb', endpoint_url=os.getenv('DYNAMODB_ENDPOINT'))
    table = dynamodb.Table('Users')
    user_id = event['queryStringParameters']['id']
    user_name = event['queryStringParameters']['name']
    
    table.put_item(
        Item={
            'id': user_id,
            'name': user_name
        }
    )
    
    # S3にファイルをアップロード
    s3 = boto3.client('s3', endpoint_url=os.getenv('S3_ENDPOINT'))
    s3.put_object(Bucket='my-bucket', Key=f'{user_id}.txt', Body=f'User: {user_name}')
    
    # SQSにメッセージを送信
    sqs = boto3.client('sqs', endpoint_url=os.getenv('SQS_ENDPOINT'))
    queue_url = os.getenv('SQS_QUEUE_URL')
    sqs.send_message(QueueUrl=queue_url, MessageBody=json.dumps({'id': user_id, 'name': user_name}))
    
    return {
        'statusCode': 200,
        'body': json.dumps({'message': 'User created successfully'})
    }

この関数は、APIリクエストからユーザー情報を受け取り、DynamoDBに保存し、S3にファイルをアップロードし、SQSにメッセージを送信します。

DynamoDBテーブルの作成

次に、DynamoDBテーブルを作成します。
以下のコマンドを実行してください。

aws dynamodb create-table \
    --table-name Users \
    --attribute-definitions AttributeName=id,AttributeType=S \
    --key-schema AttributeName=id,KeyType=HASH \
    --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
    --endpoint-url=http://localhost:4566

S3バケットの作成

S3バケットを作成します。

aws s3api create-bucket \
    --bucket my-bucket \
    --create-bucket-configuration LocationConstraint=ap-northeast-1 \
    --endpoint-url=http://localhost:4566

SQSキューの作成

SQSキューを作成し、キューURLを取得します。

QUEUE_URL=$(aws sqs create-queue --queue-name my-queue --endpoint-url=http://localhost:4566 --query 'QueueUrl' --output text)
echo $QUEUE_URL

このURLは後でLambda関数に環境変数として渡します。

Lambda関数のデプロイ

Lambda関数をデプロイするために、まずZIPファイルを作成します。

zip lambda_function.zip lambda_function.py

次に、Lambda関数を作成します。

aws lambda create-function \
    --function-name my-function \
    --runtime python3.9 \
    --handler lambda_function.handler \
    --zip-file fileb://lambda_function.zip \
    --role arn:aws:iam::000000000000:role/lambda-role \
    --environment Variables="{DYNAMODB_ENDPOINT=http://localhost:4566,S3_ENDPOINT=http://localhost:4566,SQS_ENDPOINT=http://localhost:4566,SQS_QUEUE_URL=$QUEUE_URL}" \
    --endpoint-url=http://localhost:4566

注: --roleにはダミーのARNを指定していますが、LocalStackでは実際の権限チェックは行われません。

API Gatewayの設定

API Gatewayを設定し、Lambda関数と連携させます。
以下のステップを順に実行してください。

1. APIの作成

API_ID=$(aws apigateway create-rest-api --name 'MyAPI' --endpoint-url=http://localhost:4566 --query 'id' --output text)
echo $API_ID

2. リソースの取得

ROOT_RESOURCE_ID=$(aws apigateway get-resources --rest-api-id $API_ID --endpoint-url=http://localhost:4566 --query 'items[0].id' --output text)
echo $ROOT_RESOURCE_ID

3. 新しいリソースの作成

RESOURCE_ID=$(aws apigateway create-resource --rest-api-id $API_ID --parent-id $ROOT_RESOURCE_ID --path-part 'users' --endpoint-url=http://localhost:4566 --query 'id' --output text)
echo $RESOURCE_ID

4. メソッドの作成(POST)

aws apigateway put-method --rest-api-id $API_ID --resource-id $RESOURCE_ID --http-method POST --authorization-type "NONE" --endpoint-url=http://localhost:4566

5. Lambda関数との統合

aws apigateway put-integration \
    --rest-api-id $API_ID \
    --resource-id $RESOURCE_ID \
    --http-method POST \
    --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:my-function/invocations \
    --endpoint-url=http://localhost:4566

6. デプロイ

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

7. Lambda関数の権限付与

API GatewayからLambda関数を呼び出せるように権限を付与します。

aws lambda add-permission \
    --function-name my-function \
    --statement-id apigateway-test-2 \
    --action "lambda:InvokeFunction" \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-east-1:000000000000:$API_ID/dev/POST/users" \
    --endpoint-url=http://localhost:4566

API Gateway構成図

API GatewayとLambdaの連携を以下の図で確認しましょう。

図3: API GatewayとLambdaの連携シーケンス

サンプルコードの実装

次に、サーバーレスアプリケーションを操作するためのPythonコードを実装します。
このコードでは、API Gatewayを介してユーザー情報を追加し、DynamoDB、S3、SQSにデータを保存します。

# app.py
import requests
import json

API_ID = 'YOUR_API_ID'  # 実際のAPI IDに置き換えてください
API_URL = f'http://localhost:4566/restapis/{API_ID}/dev/_user_request_/users'

def create_user(user_id, user_name):
    params = {
        'id': user_id,
        'name': user_name
    }
    response = requests.post(API_URL, params=params)
    if response.status_code == 200:
        print('User created successfully.')
    else:
        print('Failed to create user:', response.text)

if __name__ == '__main__':
    create_user('1', 'Alice')
    create_user('2', 'Bob')

注意: API_ID部分は、実際に作成したAPI IDに置き換えてください。API IDは前のステップで取得した$API_IDを使用します。

データフロー図

ユーザー作成リクエストのデータフローを以下の図で示します。

図4: ユーザー作成時のデータフロー

動作確認で安心!

すべての設定が完了したら、動作を確認してみましょう。

1. ユーザーの作成

app.pyを実行して、ユーザーを作成します。

python app.py

正常に動作すれば、以下のように表示されます。

User created successfully.
User created successfully.

2. DynamoDBの確認

DynamoDBにデータが追加されているか確認します。

aws dynamodb scan --table-name Users --endpoint-url=http://localhost:4566

出力例:

{
    "Items": [
        {
            "id": {
                "S": "1"
            },
            "name": {
                "S": "Alice"
            }
        },
        {
            "id": {
                "S": "2"
            },
            "name": {
                "S": "Bob"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2
}

3. S3の確認

S3バケットにファイルがアップロードされているか確認します。

aws s3 ls s3://my-bucket --endpoint-url=http://localhost:4566

出力例:

2024-04-27 12:00:00          12 1.txt
2024-04-27 12:00:00          10 2.txt

4. SQSの確認

SQSキューにメッセージが送信されているか確認します。

aws sqs receive-message --queue-url $QUEUE_URL --endpoint-url=http://localhost:4566

出力例:

{
    "Messages": [
        {
            "MessageId": "12345",
            "ReceiptHandle": "abcdef",
            "MD5OfBody": "e99a18c428cb38d5f260853678922e03",
            "Body": "{\"id\": \"1\", \"name\": \"Alice\"}"
        },
        {
            "MessageId": "67890",
            "ReceiptHandle": "ghijkl",
            "MD5OfBody": "ab56b4d92b40713acc5af89985d4b786",
            "Body": "{\"id\": \"2\", \"name\": \"Bob\"}"
        }
    ]
}

動作確認フロー図

動作確認のステップを以下の図で表現します。

図5: 動作確認のフローチャート

まとめ

今回、LocalStackを使用して0円でサーバーレス開発環境を構築する方法を紹介しました。

LocalStackを活用することで、AWSの各種サービスをローカルでエミュレートし、開発・テストを効率的に行うことが可能です。
特に、コストを抑えたい初心者や、クラウドに依存せずに開発を進めたい方には最適なツールです。

いつまでも0円で使用せず、売上を上げてAWSへお金を払えるようにしたいですね!

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?