
AWS Emulator がリリースされたので試してみた
はじめに
AWS は2026年11月11日に、ローカル用のエミュレータ AWS Emulator の提供開始を発表しました。
この記事では、AWS Emulator v1.0.322 を Docker で起動し、AWS SDK や AWS CLI の呼び出し先をローカルの AWS Emulator のエンドポイントに切り替えて、S3・SQS・DynamoDB・Lambda の基本操作を実行しました。
あわせて、起動時間、メモリ使用量、イメージサイズを、OSS のローカルエミュレーターである Floci 2.4.0 と比較しました。
起動と接続
イメージのビルド
Docker 用のビルド済みイメージはなく、User Guide の Dockerfile からビルドします。今回は aarch64 のホストで試したため、ADD 行の RPM だけを aarch64 用に変えています。
Dockerfile という名前で次の内容を保存します。
Dockerfile(aarch64 用)
FROM public.ecr.aws/amazonlinux/amazonlinux:2023-minimal
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"]
この Dockerfile は aarch64 用です。x86_64 のホストでは、User Guide に掲載されている Dockerfile をそのままご利用ください。
Dockerfile のあるディレクトリを指定してビルドします。
docker build -t aws-emulator:verify <Dockerfile のあるディレクトリ>
コンテナの起動
マウントするのは専用のディレクトリです。ホストの ~/.aws 配下は使いません。
SHARE="$PWD/aws-emulator-share"
mkdir -p "$SHARE"
docker run -d --rm --name aws-emulator-verify --memory=2g --memory-swap=2g \
-p 127.0.0.1:9297:9297 --user "$(id -u):$(id -g)" \
-e EMULATOR_TELEMETRY=off \
-v "$SHARE:/home/emulator/.aws/emulator" \
aws-emulator:verify -p 9297
起動直後は接続できないため、/__admin/health が HTTP 200 を返すまで次のループで待ちます。
for i in $(seq 30); do
curl -sf --cacert "$SHARE/9297/ca.pem" https://127.0.0.1:9297/__admin/health && break
sleep 1
done
AWS CLI の向け先
向け先は環境変数で切り替えます。次の内容を env-emulator.sh として保存します。このスクリプトは変数 SHARE を参照するため、前の手順で SHARE を設定したシェルで読み込みます。
env-emulator.sh
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_PROFILE
_S="$SHARE/9297"
export AWS_ENDPOINT_URL=https://127.0.0.1:9297
export AWS_SHARED_CREDENTIALS_FILE="$_S/emulator_credentials"
export AWS_CONFIG_FILE="$_S/config"
export AWS_CA_BUNDLE="$_S/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
読み込んでから、呼び出しがエミュレータに届いていることを確認します。
source env-emulator.sh
aws sts get-caller-identity
{
"Account": "000000000000",
"Arn": "arn:aws:iam::000000000000:user/emulator"
}
000000000000 はエミュレータの固定アカウント ID です。
動作確認
以降のコマンドは、環境変数を読み込んだシェルで実行しました。
S3
バケットの作成、標準入力からのアップロード、一覧の取得、ダウンロードは、いずれも通常の aws s3 コマンドで実行できました。data0.json の中身は {"hello":"world"} です。
aws s3 mb s3://my-bucket
cat data0.json | aws s3 cp - s3://my-bucket/data.json
aws s3 ls s3://my-bucket
aws s3 cp s3://my-bucket/data.json ./downloaded.json && cat downloaded.json
make_bucket: my-bucket
2026-11-12 10:52:34 18 data.json
{"hello":"world"}
次に、バージョニングを有効にしました。そのうえで、内容が {"hello":"world","version":2} の data2.json を同じキーに上書きし、バージョン一覧を取得しました。
aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Enabled
aws s3 cp data2.json s3://my-bucket/data.json
aws s3api list-object-versions --bucket my-bucket
{
"Size": 30,
"Key": "data.json",
"VersionId": "<version-id>",
"IsLatest": true
},
{
"Size": 18,
"Key": "data.json",
"VersionId": "null",
"IsLatest": false
}
有効化前にアップロードしたオブジェクトの VersionId は、文字列の "null" でした。
presign URL は、パス形式の https URL で発行されました。認証情報と署名はマスクしています。
aws s3 presign s3://my-bucket/data.json --expires-in 3600
https://127.0.0.1:9297/my-bucket/data.json?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<masked>&X-Amz-Date=20261112T015236Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=<masked>
curl の --cacert にエミュレータの ca.pem を渡してこの URL にアクセスすると、HTTP 200 で最新バージョンの内容が返りました。
URL=$(aws s3 presign s3://my-bucket/data.json --expires-in 3600)
curl -s -w "\nhttp_code=%{http_code}\n" --cacert "$SHARE/9297/ca.pem" "$URL"
{"hello":"world","version":2}
http_code=200
SQS
標準キューを作成すると、QueueUrl のホストは sqs.us-east-1.amazonaws.com でした。URL に含まれる 000000000000 も、エミュレータの固定アカウント ID です。
aws sqs create-queue --queue-name orders
{
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/000000000000/orders"
}
この URL をそのまま --queue-url に渡して、送信と受信ができました。受信の応答は、本文と受信回数の部分だけを抜粋しています。
aws sqs send-message \
--queue-url https://sqs.us-east-1.amazonaws.com/000000000000/orders \
--message-body '{"event":"order.placed","id":"abc123"}'
aws sqs receive-message \
--queue-url https://sqs.us-east-1.amazonaws.com/000000000000/orders \
--max-number-of-messages 10 \
--attribute-names All
{
"Messages": [
{
"Body": "{\"event\":\"order.placed\",\"id\":\"abc123\"}",
"Attributes": {
"ApproximateReceiveCount": "1"
}
}
]
}
FIFO キューも作成でき、一覧に含まれました。
aws sqs create-queue --queue-name orders.fifo --attributes FifoQueue=true
aws sqs list-queues
{
"QueueUrls": [
"https://sqs.us-east-1.amazonaws.com/000000000000/orders",
"https://sqs.us-east-1.amazonaws.com/000000000000/orders.fifo"
]
}
DynamoDB
テーブルを作成し、応答からテーブルの状態(TableStatus)だけを取り出しました。
aws dynamodb create-table \
--table-name Users \
--attribute-definitions AttributeName=userId,AttributeType=S \
--key-schema AttributeName=userId,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--query TableDescription.TableStatus \
--output text
CREATING
状態が CREATING だったため、aws dynamodb wait table-exists で ACTIVE になるまで待ちました。待ち時間は、前後に date で時刻を出力して測っています。
date +%H:%M:%S.%N
aws dynamodb wait table-exists --table-name Users
echo "wait_exit=$?"
date +%H:%M:%S.%N
aws dynamodb describe-table --table-name Users --query Table.TableStatus --output text
11:06:37.290630503
wait_exit=0
11:06:40.244624834
ACTIVE
waiter は約3秒で戻りました。続けて、アイテムの登録、取得、scan を実行しました。
aws dynamodb put-item --table-name Users --item '{"userId":{"S":"u1"},"name":{"S":"Alice"},"age":{"N":"30"}}'
aws dynamodb put-item --table-name Users --item '{"userId":{"S":"u2"},"name":{"S":"Bob"},"age":{"N":"20"}}'
aws dynamodb get-item --table-name Users --key '{"userId":{"S":"u1"}}'
{
"Item": {
"name": {
"S": "Alice"
},
"userId": {
"S": "u1"
},
"age": {
"N": "30"
}
}
}
age が25より大きいという条件で scan すると、ScannedCount が2件、Count が1件でした。
aws dynamodb scan \
--table-name Users \
--filter-expression 'age > :min' \
--expression-attribute-values '{":min":{"N":"25"}}'
"Count": 1,
"ScannedCount": 2,
Lambda
IAM ロールは作成せず、ロールの ARN だけを指定して、ランタイムが nodejs22.x の関数を作成しました。関数コードの index.mjs は、この節の末尾に載せています。
zip function.zip index.mjs
aws lambda create-function \
--function-name my-function \
--runtime nodejs22.x \
--role arn:aws:iam::000000000000:role/lambda-role \
--handler index.handler \
--zip-file fileb://function.zip \
--query '{FunctionName:FunctionName,Runtime:Runtime,Handler:Handler,State:State}'
{
"FunctionName": "my-function",
"Runtime": "nodejs22.x",
"Handler": "index.handler",
"State": "Pending"
}
State が Pending だったため、aws lambda wait function-active-v2 で待ち、DynamoDB と同じく前後の時刻を出しました。
date +%H:%M:%S.%N
aws lambda wait function-active-v2 --function-name my-function
echo "wait_exit=$?"
date +%H:%M:%S.%N
aws lambda get-function-configuration --function-name my-function --query '{State:State,LastUpdateStatus:LastUpdateStatus}'
11:06:42.621728900
wait_exit=0
11:06:43.992666608
{
"State": "Active",
"LastUpdateStatus": "Successful"
}
waiter は約1.4秒で戻りました。
同期で Invoke すると、StatusCode 200 が返り、response.json に関数の戻り値が入っていました。
aws lambda invoke \
--function-name my-function \
--payload '{"key":"value"}' \
--cli-binary-format raw-in-base64-out \
response.json
cat response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
{"statusCode":200,"body":"{\"hello\":\"world\",\"received\":{\"key\":\"value\"}}"}
index.mjs
export const handler = async (event) => {
console.log("Event:", JSON.stringify(event));
return { statusCode: 200, body: JSON.stringify({ hello: "world", received: event }) };
};
対応サービス数
AWS CLI 2.40.0 の aws help で確認できる435のサービスのうち、AWS Emulator v1.0.322 のモデルが無いのは importexport(AWS Import/Export)と sdb(Amazon SimpleDB)の2件だけでした。
リソース消費
計測条件
OSS 実装の AWS エミュレーター Floci と、リソース消費などを比較しました。
計測には、ほかのコンテナも動いている aarch64 の Linux 作業機を使いました。Docker のバージョンは 29.9.3 です。AWS Emulator と Floci のどちらにも --memory=2g --memory-swap=2g を指定し、ポートは 127.0.0.1 だけに公開しました。AWS Emulator は自分でビルドしたイメージ、Floci は floci/floci:2.4.0 のイメージを使っています。
起動時間は、docker run の開始から HTTP 200 が返るまでの時間です。AWS Emulator は /__admin/health、Floci は http://127.0.0.1:4566/ に問い合わせました。ポーリングは0.02秒間隔で、イメージのビルド時間は含みません。この値は別途計測したもので、「コンテナの起動」の1秒間隔のループでかかった時間ではありません。
アイドル時メモリは、起動から約10秒後(AWS Emulator)と約16秒後(Floci)に取得しました。S3 バケットを作成した後にも、同じ方法で取得しています。メモリは docker stats --no-stream の MEM USAGE 列、イメージサイズは docker image ls の DISK USAGE 列の値です。
docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}\t{{.PIDs}}' aws-emulator-verify
docker image ls aws-emulator:verify
docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}\t{{.PIDs}}' floci-verify
docker image ls floci/floci:2.4.0
Floci の起動コマンド
docker run -d --rm --name floci-verify --memory=2g --memory-swap=2g \
-p 127.0.0.1:4566:4566 \
--tmpfs /app/data \
floci/floci:2.4.0
計測結果
各値は1回だけ測定した結果です。
| 指標 | AWS Emulator v1.0.322 | Floci 2.4.0 |
|---|---|---|
| 起動時間 | 0.257秒 | 0.431秒 |
| アイドル時メモリ | 173.9MiB | 34.12MiB |
| S3 バケット作成後のメモリ | 177.6MiB | 37.62MiB |
| イメージサイズ(DISK USAGE) | 1.62GB | 367MB |
まとめ
AWS Emulator の ARM 版を Docker 環境上で動かし、S3・SQS・DynamoDB・Lambda の基本操作を AWS CLI から実行できることを確認できました。
AWS サービスのローカルエミュレーターには、LocalStack やオープンソースプロジェクトの Floci があります。AWS Emulator が AWS 純正ツールとしてリリースされたことで、高い再現性や新機能への追従、サポートの向上にも期待できます。
AWS Emulator v1.0.322 で提供されるモデルは433と充実していますが、IAM ポリシーとリソースベースのポリシーなど、実サービスと異なる仕様に留意しつつ、AWS サービスのローカル開発や CI などでご活用ください。








