--- title: "AWS Emulatorを利用して、ローカルでAWS APIを再現する" description: "AWS公式のローカルエミュレータ「AWS Emulator」をDockerで動かし、S3とLambdaを試して使用感を確かめます。" createdAt: "2026-11-13T23:09:19+09:00" tags: [ソフトウェアエンジニアリング, AWS Emulator] --- 2026-11-12に、[AWS Emulator](https://aws.amazon.com/jp/blogs/news/test-your-applications-against-aws-locally-with-aws-emulator/) という仕組みがAWS公式によりリリースされました。 AWSのAPIをローカル上に立てて動作検証ができたりするということで、とても良さそうなので簡単に触ってみて使用感を確かめます。 ## 環境 macOS 26.6.2 ```bash > docker --version Docker version 29.7.2, build a7dcaa6 > aws --version aws-cli/2.36.44 Python/3.14.6 Darwin/25.6.0 script-exe/arm64 > uv --version uv 0.13.8 (Homebrew 2026-11-12 aarch64-apple-darwin) ``` ## セットアップ AWS EmulatorはDockerを利用して動かすことができるみたいなので、動かすためのDockerfileを定義します。 ```Dockerfile FROM public.ecr.aws/amazonlinux/amazonlinux@sha256:158a9044f9dc0777f098b76c8b54346f6ed4560b9a6a416dec7a5ba3bc483af4 ADD https://downloads.aws.com/aws-emulator/packages/aws-emulator/LTS/latest/aws-emulator-aarch64.rpm /tmp/aws-emulator.rpm RUN rpm -i /tmp/aws-emulator.rpm && rm /tmp/aws-emulator.rpm && mkdir -p /home/emulator && chown 1000 /home/emulator USER 1000 ENV HOME=/home/emulator EXPOSE 9297 ENTRYPOINT ["aws-emulator", "-b", "0.0.0.0"] ``` buildして動作を確認します。 ```bash > docker build -t aws-emulator . > docker run --rm aws-emulator --version ``` 動作確認が取れたら、別にターミナルウインドウを開いて以下を実行します。aws-emulatorが起動してpending状態になっていることを確認します。 ```bash > docker run --rm --memory=2g --memory-swap=2g -p 127.0.0.1:9297:9297 \ -e HOME="$HOME" -v "$HOME/.aws/emulator:$HOME/.aws/emulator" \ aws-emulator -p 9297 --telemetry off ``` [公式の手順](https://docs.aws.amazon.com/emulator/latest/userguide/point-sdk-to-emulator.html#point-sdk-env)に則って環境変数を設定して、aws-emulatorとの疎通ができることを確認します。 ```bash > export AWS_ENDPOINT_URL=https://127.0.0.1:9297 > export AWS_SHARED_CREDENTIALS_FILE=~/.aws/emulator/9297/emulator_credentials > export AWS_CONFIG_FILE=~/.aws/emulator/9297/config > export AWS_CA_BUNDLE=~/.aws/emulator/9297/ca.pem > export AWS_EC2_METADATA_DISABLED=true > export AWS_DISABLE_HOST_PREFIX_INJECTION=true > export AWS_REGION=us-east-1 > export AWS_DEFAULT_REGION=us-east-1 # health check > curl -sf --cacert ~/.aws/emulator/9297/ca.pem https://127.0.0.1:9297/__admin/health ok > aws sts get-caller-identity { "UserId": "***", "Account": "000000000000", "Arn": "arn:aws:iam::000000000000:user/emulator" } ``` ## 試してみる ### S3バケットを作ってファイルをアップロードする ここまででAWS Emualtorを利用して擬似的にローカルでAWS APIが利用できるようになったので、試しにS3にバケットを作って、ファイルをアップロードしてみます。 ```bash export BUCKET=emu-demo > aws s3 mb "s3://$BUCKET" > printf 'hello world\nこんにちは 世界\n' > sample.txt > time aws s3 cp sample.txt "s3://$BUCKET/sample.txt" # 作成したバケット状にファイルがアップロードされていることを確認 > aws s3 ls "s3://$BUCKET" --recursive sample.txt ``` S3を利用したファイルのやり取りはローカルに閉じる形で実現できることがわかりました。 ### Lambda関数を作って実行する S3上のファイルを読み込んで、単純なprintを行うようなLambda関数を作って動かしてみます。 Lambda関数本体は次のようにしました。 ```python title="handler.py" """S3 に置かれたオブジェクトを読んで、中身をそのまま print する Lambda 関数。""" import boto3 s3 = boto3.client("s3") def handler(event, context): record = event["Records"][0]["s3"] bucket = record["bucket"]["name"] key = record["object"]["key"] body = s3.get_object(Bucket=bucket, Key=key)["Body"].read() print(f"s3://{bucket}/{key}") print(body.decode("utf-8")) return {"bucket": bucket, "key": key, "bytes": len(body)} ``` lambda用のポリシーと、先ほど作成したs3バケット内ののオブジェクトをreadするためのポリシーを用意して、iam roleにattachします。 ```bash > cat > /tmp/lambda-policy.json <<'EOF' {"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]} EOF > cat > /tmp/s3-policy.json <<'EOF' {"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::emu-demo/*"}]} EOF > export ROLE_ARN=$(aws iam create-role --role-name print-s3-content-role \ --assume-role-policy-document file://./lambda-policy.json \ --query Role.Arn --output text) > aws iam put-role-policy --role-name print-s3-content-role \ --policy-name s3-read --policy-document file://./s3-policy.json ``` > [!NOTE] > AWS EmulatorはIAMポリシーをAWSと同じようには評価しません。ここではロールとポリシーを作成していますが、LambdaがS3を読み取れるかどうかはポリシーでは制御されません。詳細は[公式ブログ](https://aws.amazon.com/jp/blogs/news/test-your-applications-against-aws-locally-with-aws-emulator/)や[ドキュメントの制限事項](https://docs.aws.amazon.com/emulator/latest/userguide/what-is-service.html#what-is-limits)を参照してください。 先ほど作成したhandlerを動かすlambda関数を作成します ```bash > zip -q function.zip handler.py > aws lambda create-function --function-name print-s3-content --runtime python3.14 \ --handler handler.handler --role "$ROLE_ARN" \ --zip-file fileb://function.zip --timeout 30 > aws lambda wait function-active-v2 --function-name print-s3-content > aws lambda get-function --function-name print-s3-content --query 'Configuration.[State,Runtime]' [ "Active", "python3.14" ] ``` lambda関数をキックするスクリプトを実行して、意図通りにファイルの内容がprintされるかを確認します。 ```python title="invoke.py" import base64 import json import sys from pathlib import Path import boto3 FUNCTION_NAME = "print-s3-content" KEY = "sample.txt" def main(bucket: str) -> None: s3 = boto3.client("s3") lam = boto3.client("lambda") body = Path(__file__).with_name("sample.txt").read_bytes() s3.put_object(Bucket=bucket, Key=KEY, Body=body) event = { "Records": [ { "eventSource": "aws:s3", "eventName": "ObjectCreated:Put", "awsRegion": "us-east-1", "s3": { "bucket": {"name": bucket}, "object": {"key": KEY}, }, } ] } response = lam.invoke( FunctionName=FUNCTION_NAME, Payload=json.dumps(event).encode("utf-8"), LogType="Tail", ) print(base64.b64decode(response["LogResult"]).decode("utf-8")) if __name__ == "__main__": if len(sys.argv) != 2: raise SystemExit("usage: python put_and_invoke.py ") main(sys.argv[1]) ``` ```bash > uv run python invoke.py "$BUCKET" hello world こんにちは 世界 ``` emulatorのS3上にアップロードしたファイルを利用してLambda関数が動作することを確認できました。 ## まとめ AWS Emulator、とても良いと思います。 従来も[Local Stack](https://www.localstack.cloud/)のような似たようなコンセプトのものはありましたが、AWS公式から提供されているというのが安心感があって良いですね。 AI Agentとの親和性については言わずもがなですし、CIに組み込むような使い方もとても価値があります。 時代に即したツールをすぐに提供してくれるAWSはやはり信頼感があって良いなと思いました。