AWS Emulatorを利用して、ローカルでAWS APIを再現する
2026-11-12に、AWS Emulator という仕組みがAWS公式によりリリースされました。
AWSのAPIをローカル上に立てて動作検証ができたりするということで、とても良さそうなので簡単に触ってみて使用感を確かめます。
環境
macOS 26.6.2
> 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を定義します。
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して動作を確認します。
> docker build -t aws-emulator .
> docker run --rm aws-emulator --version
動作確認が取れたら、別にターミナルウインドウを開いて以下を実行します。aws-emulatorが起動してpending状態になっていることを確認します。
> 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
公式の手順に則って環境変数を設定して、aws-emulatorとの疎通ができることを確認します。
> 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にバケットを作って、ファイルをアップロードしてみます。
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関数本体は次のようにしました。
"""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します。
> 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
先ほど作成したhandlerを動かすlambda関数を作成します
> 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されるかを確認します。
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 <bucket-name>")
main(sys.argv[1])> uv run python invoke.py "$BUCKET"
hello world
こんにちは 世界
emulatorのS3上にアップロードしたファイルを利用してLambda関数が動作することを確認できました。
まとめ
AWS Emulator、とても良いと思います。 従来もLocal Stackのような似たようなコンセプトのものはありましたが、AWS公式から提供されているというのが安心感があって良いですね。
AI Agentとの親和性については言わずもがなですし、CIに組み込むような使い方もとても価値があります。
時代に即したツールをすぐに提供してくれるAWSはやはり信頼感があって良いなと思いました。