AWSのサービスをローカルで利用できると聞いたので、空き時間に導入してみました。
LocalStackとは
LocalStackは、AWSの環境をローカルでエミュレートするツールです。クラウドに接続せずにAWSサービスの一部を利用して開発・テストができます。無料のCommunity版と有料版があり、Community版ではデータの保持がされず、Dockerコンテナを停止するとすべてのデータが削除されるようです。Community版でも商用利用が可能です。有料版ではより多くのAPIが使えます。
インストール方法
LocalStackは環境に合わせた複数のインストール方法があります。
https://docs.localstack.cloud/getting-started/installation/
①LocalStack CLI
 CLIだけでもLocalStack環境を作成できます。他のインストール方法を選択した場合でも、コマンドでLocalStackを操作する際に、このツールがあると便利です。
②LocalStack Desktop
 GUIで操作が行えます。詳しくは後述します。
③LocalStack Docker Extension
 Docker DesktopでLocalStackを操作できるようになります。Docker Desktop内のExtensionsからインストールします。
④Docker-Compose
 docker-compose.yamlでLocalStackコンテナの設定、他コンテナとの連携ができます。拡張性があり、扱いやすいため、こちらを今回は使います。
⑤Docker
 Docker CLIでもLocalStackコンテナを起動できます。
⑥Helm
 Kubernetes環境でLocalStackを動かせるようです。
導入手順
LocalStack CLIのインストール
brew install awscli-localいつものAWS CLIコマンドをawslocalに置き換えることで、同じ使い勝手で利用できるようになります。
AWS CLIコマンドでもLocalStackで実行できますが、その際はエンドポイントの指定が必要です。
LocalStack環境をクローン
git clone https://github.com/localstack/localstack.gitdocker-compose.ymlファイルがlocalstack直下に格納されていますので実行します。
cd localstack/
docker compose up -ddocker-compose.ymlの内容です。
services:
  localstack:
    container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}"
    image: localstack/localstack
    ports:
      - "127.0.0.1:4566:4566"            # LocalStack Gateway
      - "127.0.0.1:4510-4559:4510-4559"  # external services port range
    environment:
      - DEBUG=${DEBUG:-0}
    volumes:
      - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"enviromentセクションでPERSISTENCE=1 を記述するとデータが永続化するらしいですが機能しませんでした。
データ永続化はどうやら有料版のみらしいですが、Community版でも対応方法あるようです。
https://github.com/localstack/localstack/issues/6281
コンテナが起動すれば、LocalStackの環境が完成です。次にAWSサービスを作成していきます。
AWSサービスの作成
LocalStackで利用できる無料サービスを確認します。
localstack status services
acm, apigateway, cloudformation, cloudwatch, config, dynamodb, dynamodbstreams, ec2, es, 
events, firehose, iam, kinesis, kms, lambda, logs, opensearch, redshift, 
resource-groups, resourcegroupstaggingapi, route53, route53resolver, s3, s3control, scheduler, secretsmanager, ses, sns, sqs, ssm, stepfunctions, sts, support, swf, transcribe
有料版では他に下記サービス等が利用できるようです。
https://docs.localstack.cloud/user-guide/aws/feature-coverage
RDS, CloudFront, Step Functions, AppSync, Glue, Athena, EMR試しにS3にファイルがアップロードされた際にLambda関数を起動させてみます。
LocalStackのコマンドでAWSサービスを作成する方法があるのですが一つずつ作成していくと面倒なので
CloudFormationを使用して一括でAWSリソースを作成します。
# ファイル名:template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  TestBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: test-bucket
      NotificationConfiguration:
        LambdaConfigurations:
          - Event: "s3:ObjectCreated:*"
            Function: !GetAtt S3EventProcessorFunction.Arn
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: lambda-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: LambdaS3AccessPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:ListBucket
                Resource:
                  - arn:aws:s3:::test-bucket
                  - arn:aws:s3:::test-bucket/*
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "arn:aws:logs:*:*:*"
  # Lambda関数の作成
  S3EventProcessorFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: S3EventProcessor
      Handler: lambda_function.handler
      Runtime: nodejs18.x
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            console.log("Test Lambda Event received:", JSON.stringify(event, null, 2));
            return { statusCode: 200, body: "Success" };
          };
  # Lambdaターゲットへの権限の付与
  AllowS3InvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref S3EventProcessorFunction
      Action: lambda:InvokeFunction
      Principal: s3.amazonaws.com
      SourceArn: !GetAtt TestBucket.ArnCloudFormationをLocalStack上にデプロイします。
awslocal cloudformation create-stack --stack-name test-stack --template-body file://template.yaml各サービスが作成されているか確認します。
Lambda関数の確認
awslocal lambda list-functions
S3バケットの確認
awslocal s3 ls
CloudFormationスタックの確認
awslocal cloudformation describe-stacks --stack-name test-stack作成されてないと、空のオブジェクトが返ってきたり、エラーメッセージが表示されたりします。
Lambda関数の動作確認
ファイルをS3にアップロードし、Lambda関数が実行されるか確認します。
awslocal s3 cp test.csv s3://test-bucketClouldWatchを確認します。まずログストリーム名を確認します。
awslocal logs describe-log-streams --log-group-name /aws/lambda/S3EventProcessoreams --log-group-name /aws/lambda/S3EventProcessor
    {
        "logStreams": [
           {
            "logStreamName": "2024/09/25/[$LATEST]0b4cc733d291d4a3cc4ff54151732e47",
            "creationTime": 1727251875453,
            "firstEventTimestamp": 1727251875441,
            "lastEventTimestamp": 1727251875448,
            "lastIngestionTime": 1727251875456,
            "uploadSequenceToken": "1",
            "arn": "arn:aws:logs:ap-northeast-1:000000000000:log-group:/aws/lambda/S3EventProcessor:log-stream:2024/09/25/[$LATEST]0b4cc733d291d4a3cc4ff54151732e47",
            "storedBytes": 1335
        }
        ]
    }logStreamNameからログを取得します。
awslocal logs get-log-events --log-group-name /aws/lambda/S3EventProcessor --log-stream-name '2024/09/25/[$LATEST]0b4cc733d291d4a3cc4ff54151732e47'
    {
        "events": [
            {
                "timestamp": 1727251875441,
                "message": "START RequestId: b48d6c83-db3a-47dc-82da-a53b88110de5 Version: $LATEST",
                "ingestionTime": 1727251875456
            },
            {
                "timestamp": 1727251875443,
               "message": "2024-09-25T08:11:15.436Z\tb48d6c83-db3a-47dc-82da-a53b88110de5\tINFO\tTest Lambda Event received: {\
       \"eventSource\": \"aws:s3\
       \"eventName\": \"ObjectCreated:Put\",\r 
       \"arn\": \"arn:aws:s3:::test-bucket\"\
       "object\": {\r          \"key\": \"test.csv\",\
(抜粋/整形してます。)Lambda関数のコード内に仕込んだ”Test Lambda Event received”というログメッセージが、S3バケットへのPutObjectイベントによってトリガーされ、ログに表示されていることが確認できました。
外部サービスとの連携
S3にデータを保持して起きたい場合には、MinIOというS3互換のストレージサービスが便利かと思います。
ローカル用のコンテナイメージが提供されています。
GUIでの表示
非営利目的ならデスクトップアプリケーションが利用できるようです。
https://docs.localstack.cloud/user-guide/tools/localstack-desktop/
まとめ
LocalStackを利用することでローカル環境にAWSサービスを作成し動作させることができました。LocalStackを導入することで、AWSクラウド上でしかテストできなかった開発環境が、ローカルでもテストできるようになるでしょう。AWSサービスが必要なために動作しなかったローカル開発環境も、LocalStackを使うことで動作するようになると思います。クラウドリソースとアプリケーションの連携をローカルで確認するのにLocalStackは非常に有用ではないでしょうか。
また、AWSの学習においても、費用やセキュリティを気にせずに利用できるのは便利だと思います。AWSの利用料を気にしていては、学習効率が上がりませんからね。学習目的であればLocalStack Desktopを活用するのも良いですね!
![[LocalStack]無料でAWSサービスを開発・テストする](https://i0.wp.com/engineering-wp.mobalab.net/wp-content/uploads/2020/04/aws_logo_smile_1200x630.png?fit=1200%2C630&ssl=1) 
 
	 
							 
							