The AWS Emulator, ready to run in Docker.
AWS does not publish a prebuilt image of its local AWS API emulator. This project builds one, tests it on both architectures, signs it, and publishes it to three registries. A new upstream release is live within one hour.
docker run --rm -p 127.0.0.1:9297:9297 ghcr.io/xsavikx/aws-emulator
Write-up with docker run, Compose, GitHub Actions and the gotchas: Running AWS Emulator in Docker, on any arch, in CI.
Native amd64 and arm64 builds. Runs on Linux, on macOS (Intel and Apple silicon) and on Windows with Docker Desktop.
A pinned upstream version, with an SHA-256 check and an RPM signature check against the AWS signing key.
Keyless cosign signature, SBOM, SLSA provenance and a GitHub artifact attestation.
Each build runs STS and S3 calls and a health check on both architectures before it is published.
Quick start
The emulator writes its credentials, configuration and TLS certificate to ~/.aws/emulator/<port>/. Mount that directory, so your AWS CLI and SDKs can read the files.
Step 1. Create the directory. Step 2. Start the emulator.
mkdir -p ~/.aws/emulator
PORT=9297
docker run --rm --memory=2g --memory-swap=2g -p 127.0.0.1:$PORT:$PORT \
--user "$(id -u):$(id -g)" \
-e HOME="$HOME" -v "$HOME/.aws/emulator:$HOME/.aws/emulator" \
ghcr.io/xsavikx/aws-emulator -p $PORT
With rootless Docker, container root maps to your host user. Your own UID, or no --user, fails with Permission denied (os error 13).
mkdir -p ~/.aws/emulator
PORT=9297
docker run --rm --memory=2g --memory-swap=2g -p 127.0.0.1:$PORT:$PORT \
--user 0:0 \
-e HOME="$HOME" -v "$HOME/.aws/emulator:$HOME/.aws/emulator" \
ghcr.io/xsavikx/aws-emulator -p $PORT
New-Item -ItemType Directory -Force "$env:USERPROFILE\.aws\emulator"
$port = 9297
docker run --rm --memory=2g --memory-swap=2g -p "127.0.0.1:${port}:${port}" `
-v "$env:USERPROFILE\.aws\emulator:/home/emulator/.aws/emulator" `
ghcr.io/xsavikx/aws-emulator -p $port
services:
aws-emulator:
image: ghcr.io/xsavikx/aws-emulator:latest
command: ["-p", "9297"]
user: "${UID_GID:-1000:1000}"
environment:
HOME: ${HOME}
ports:
- "127.0.0.1:9297:9297"
volumes:
- ${HOME}/.aws/emulator:${HOME}/.aws/emulator
mem_limit: 2g
memswap_limit: 2g
Start it with UID_GID="$(id -u):$(id -g)" docker compose up.
Step 3. Point the AWS CLI or an SDK at the 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 AWS_DEFAULT_REGION=us-east-1
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_PROFILE
aws sts get-caller-identity # "Account": "000000000000"
$env:AWS_ENDPOINT_URL = "https://127.0.0.1:9297"
$env:AWS_SHARED_CREDENTIALS_FILE = "$env:USERPROFILE\.aws\emulator\9297\emulator_credentials"
$env:AWS_CONFIG_FILE = "$env:USERPROFILE\.aws\emulator\9297\config"
$env:AWS_CA_BUNDLE = "$env:USERPROFILE\.aws\emulator\9297\ca.pem"
$env:AWS_EC2_METADATA_DISABLED = "true"
$env:AWS_DISABLE_HOST_PREFIX_INJECTION = "true"
$env:AWS_REGION = "us-east-1"
$env:AWS_DEFAULT_REGION = "us-east-1"
aws sts get-caller-identity
Node.js needs NODE_EXTRA_CA_CERTS. Rust and .NET need SSL_CERT_FILE. Java needs truststore.p12. See the AWS SDK guide.
Important facts
127.0.0.1. The image binds to 0.0.0.0 inside the container, so a plain -p 9297:9297 exposes the emulator to your whole network.- Same port in three places. If you change the port, change the host side of
-p, the container side of-p, and the emulator-pargument. Do not use-p 0. - TLS. The emulator creates a new self-signed certificate (
ca.pem) at each start. Your client must trust that file. - Memory. Give the container 2 GiB. Above the limit, Docker stops it with exit code 137, and you lose all emulated resources.
- No persistence. All state is in memory. A restart gives an empty emulator.
- Health check. The image has a Docker
HEALTHCHECKon/__admin/health. For another port, also set-e EMULATOR_HEALTHCHECK_PORT=<port>. - Telemetry. The upstream emulator sends anonymous usage telemetry by default. To turn it off, add
-e EMULATOR_TELEMETRY=off.
Examples
Integration tests in six languages, with the most common test framework of each language and the official AWS SDK. Every example tests the same scenarios: STS identity, S3 objects, a DynamoDB table, an SQS queue, SNS to SQS fan-out, and a Secrets Manager secret. CI runs all of them on amd64 and arm64 after each image release.
pytest + Boto3. Source and README.
import boto3
from botocore.config import Config
# Endpoint, keys, Region and CA come from the environment.
sts = boto3.client("sts")
s3 = boto3.client("s3", config=Config(s3={"addressing_style": "path"}))
sqs = boto3.client("sqs")
examples/with-emulator.sh examples/python/run-tests.sh
Vitest + AWS SDK v3. Source and README.
import { S3Client } from "@aws-sdk/client-s3";
import { SQSClient } from "@aws-sdk/client-sqs";
// Endpoint, keys, Region and CA come from the environment.
const s3 = new S3Client({ forcePathStyle: true });
// The emulator returns queue URLs with the real AWS host.
// Keep SQS requests on AWS_ENDPOINT_URL:
const sqs = new SQSClient({ useQueueUrlAsEndpoint: false });
examples/with-emulator.sh examples/typescript/run-tests.sh
JUnit 5 + AWS SDK 2.x. Source and README.
// Endpoint, keys and Region come from the environment.
// JAVA_TOOL_OPTIONS points to a truststore with the JDK CAs + emulator CA.
S3Client s3 = S3Client.builder().forcePathStyle(true).build();
SqsClient sqs = SqsClient.create();
DynamoDbClient dynamo = DynamoDbClient.create();
examples/with-emulator.sh examples/java/run-tests.sh
go test + AWS SDK v2. Source and README.
// Endpoint, keys, Region and CA (AWS_CA_BUNDLE) come from the environment.
cfg, err := config.LoadDefaultConfig(ctx)
if err != nil {
t.Fatal(err)
}
s3c := s3.NewFromConfig(cfg, func(o *s3.Options) { o.UsePathStyle = true })
sqsc := sqs.NewFromConfig(cfg)
examples/with-emulator.sh examples/go/run-tests.sh
xUnit + AWS SDK for .NET v4. Source and README.
// SDK v4 reads AWS_ENDPOINT_URL. On Linux, .NET trusts the CA through
// SSL_CERT_FILE (system CAs + emulator CA).
var s3 = new AmazonS3Client(new AmazonS3Config { ForcePathStyle = true });
var sqs = new AmazonSQSClient();
var dynamo = new AmazonDynamoDBClient();
examples/with-emulator.sh examples/dotnet/run-tests.sh
cargo test + Tokio. Source and README.
// Endpoint, keys and Region come from the environment. rustls trusts
// the CA through SSL_CERT_FILE (system CAs + emulator CA).
let config = aws_config::load_from_env().await; // feature "behavior-version-latest"
let s3 = aws_sdk_s3::Client::from_conf(
aws_sdk_s3::config::Builder::from(&config).force_path_style(true).build(),
);
let sqs = aws_sdk_sqs::Client::new(&config);
examples/with-emulator.sh examples/rust/run-tests.sh
Two rules apply in every language: use path-style S3 addresses, and make sure SQS calls go to the emulator, not to the host in the queue URL. See the examples README.
GitHub Action
Run AWS Emulator on the GitHub Marketplace
The Run AWS Emulator action runs this image in your workflow. It waits until the emulator is healthy and sets the environment, so the AWS CLI and the SDKs in the next steps use the emulator with no code change. It works on ubuntu-24.04, ubuntu-24.04-arm and any other runner with Docker.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: xSAVIKx/run-aws-emulator@v1
- run: aws sts get-caller-identity # "Account": "000000000000"
- run: make integration-test # your SDK tests use the emulator
Supported runners
| Runner | Result |
|---|---|
Ubuntu 22.04, 24.04, 26.04 and ubuntu-latest, x64 and arm64 | Supported. Tested in CI on every change, with all six language examples. |
| Self-hosted Linux with Docker or Podman | Supported. Rootless Docker and rootless Podman work. Podman is tested on Ubuntu 24.04 and 26.04. |
macOS, Windows and ubuntu-slim (GitHub-hosted) | Not supported: these runners have no Docker for Linux containers. The action stops at once with a clear message. |
For reproducible runs, pin the image to a build tag or a digest:
- uses: xSAVIKx/run-aws-emulator@v1
with:
image: ghcr.io/xsavikx/aws-emulator:1.0.322.1
Inputs
| Input | Description |
|---|---|
image | The image. Use a -debian tag for the Debian variant. Default: ghcr.io/xsavikx/aws-emulator:latest. |
port | The port on 127.0.0.1. The container uses the same port. Default: 9297. |
region | The value of AWS_REGION and AWS_DEFAULT_REGION. Default: us-east-1. |
telemetry | Upstream emulator telemetry, on or off. Default: off. |
memory | The container memory limit. Default: 2g. |
wait-timeout | Seconds to wait until the emulator is healthy. Default: 60. |
pull | Pull the image before the start. Default: false. |
engine | docker or podman. Default: empty, which means Docker if it is installed, else Podman. |
Outputs
| Output | Description |
|---|---|
endpoint-url | The endpoint, for example https://127.0.0.1:9297. |
ca-file | The emulator CA certificate (PEM). |
container | The container name, for docker logs. |
image-digest | The repository digest of the image that runs. |
Environment for the next steps
AWS_ENDPOINT_URL,AWS_SHARED_CREDENTIALS_FILE,AWS_CONFIG_FILE,AWS_REGIONandAWS_DEFAULT_REGIONpoint the CLI and SDKs at the emulator.AWS_CA_BUNDLEandNODE_EXTRA_CA_CERTScontain the emulator CA.SSL_CERT_FILE(system CAs + emulator CA) andJAVA_TOOL_OPTIONS(JDK CAs + emulator CA) are combined trust files. Downloads from Maven, NuGet and crates.io keep working in the same job.- Do not set
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYorAWS_PROFILEin the job. The SDKs use these before the emulator credentials file.
Source: xSAVIKx/run-aws-emulator. Unofficial community action.
Images and tags
| Registry | Image |
|---|---|
| GitHub Container Registry | ghcr.io/xsavikx/aws-emulator |
| Docker Hub | docker.io/xsavikx/aws-emulator |
| Quay.io | quay.io/xsavikx/aws-emulator |
| Tag | Meaning |
|---|---|
latest, lts | The newest LTS release |
1.0.322.1-<yyyymmdd>.<run> | One build. This tag never moves. Use it, or a digest, to pin. |
1.0.322.1 | The exact upstream package version |
1.0.322 | The emulator version, as aws-emulator --version reports it |
1.0, 1 | The newest release in that line |
sha-<commit> | The build from one commit of this repository |
Variants
| Variant and base image | Tags |
|---|---|
Amazon Linux (default)amazonlinux:2023-minimal | latest, 1.0.322.1, ... |
Debiandebian:trixie-slim | debian, latest-debian, 1.0.322.1-debian, ... |
Distrolessgcr.io/distroless/cc-debian13 | distroless, latest-distroless, 1.0.322.1-distroless, ... |
Each tag of the default variant has a Debian twin with the -debian suffix and a distroless twin with the -distroless suffix. The distroless variant has no shell, no package manager and no curl, so scanners report very few findings. Both install the same upstream emulator, from the .rpm or the .deb package, and both behave the same way.
Verify the image
Each image has a keyless cosign signature from GitHub Actions. Use cosign v3 or later. Cosign v2 reports "no signatures found".
cosign verify ghcr.io/xsavikx/aws-emulator:latest \
--certificate-identity-regexp '^https://github.com/xSAVIKx/aws-emulator-docker/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
gh attestation verify oci://ghcr.io/xsavikx/aws-emulator:latest --owner xSAVIKx
The build checks the upstream RPM against the AWS package signing key, SSM Publishing <ssm-publishing@amazon.com>, fingerprint 98BC F336 A3BE 53B7 34E9 67C5 2E5B F49B D940 F624. The base image is pinned by digest.
Frequently asked questions
What is the AWS Emulator?
The AWS Emulator is a local emulator of the AWS APIs from Amazon Web Services. It serves STS, S3, DynamoDB, SQS, SNS, Secrets Manager and many other services over HTTPS on 127.0.0.1, so tests and coding agents can run without an AWS account.
Does AWS publish a Docker image of the AWS Emulator?
No. The AWS guide tells you to build an image yourself from a short Dockerfile. This project builds that image for linux/amd64 and linux/arm64, tests it, signs it, and publishes it to GHCR, Docker Hub and Quay.io.
How do I run the AWS Emulator in Docker?
Create ~/.aws/emulator, then run: docker run --rm -p 127.0.0.1:9297:9297 --user "$(id -u):$(id -g)" -e HOME="$HOME" -v "$HOME/.aws/emulator:$HOME/.aws/emulator" ghcr.io/xsavikx/aws-emulator -p 9297. Then set AWS_ENDPOINT_URL=https://127.0.0.1:9297 and the other variables from the quick start.
Does the image work on macOS, Windows and Apple silicon?
Yes. The image is a Linux image for amd64 and arm64. Docker Desktop runs it on macOS with Intel or Apple silicon and on Windows with the WSL 2 backend. Windows containers are not available, because the emulator runs only on Linux.
How do I use the AWS Emulator in GitHub Actions?
Add the step uses: xSAVIKx/run-aws-emulator@v1. The Run AWS Emulator action starts the image, waits until it is healthy, and sets AWS_ENDPOINT_URL, the credentials, and the CA settings, so the AWS CLI and the SDKs in the next steps use the emulator.
Why do my SQS calls with the AWS SDK for JavaScript v3 go to real AWS?
The emulator returns queue URLs with the real AWS host, for example https://sqs.us-east-1.amazonaws.com/000000000000/my-queue. The AWS SDK for JavaScript v3 sends SQS requests to the host in the queue URL. Set useQueueUrlAsEndpoint: false on the SQSClient. The SDKs for Python, Go, Java, .NET and Rust need no setting.
Why does the emulator fail with Permission denied on rootless Docker?
With rootless Docker, container user IDs map to other host user IDs, so the emulator cannot write to the mounted directory. Use --user 0:0, because container root maps to your own host user. With Podman, use --userns=keep-id.
Should I use localhost or 127.0.0.1 in AWS_ENDPOINT_URL?
Use 127.0.0.1. With a host name such as localhost, some SDKs use virtual-hosted S3 addresses such as bucket.localhost, which do not resolve. Also use path-style S3 addresses in your S3 client.
How do I verify the image?
Each image has a keyless cosign signature, an SBOM and SLSA provenance. Run cosign verify (version 3 or later) with --certificate-identity-regexp '^https://github.com/xSAVIKx/aws-emulator-docker/' and --certificate-oidc-issuer https://token.actions.githubusercontent.com, or run gh attestation verify with --owner xSAVIKx.
Is this an official AWS project?
No. This is an unofficial community project by Yurii Serhiichuk. It is not affiliated with or endorsed by Amazon Web Services. The AWS Emulator itself is open source under CC0 1.0, with vendored code under the Apache License 2.0.
Release notes
Each new upstream version gets a release, with the image digests, the verified upstream packages and a summary of the upstream changes. Subscribe with the Atom feed, or watch the repository on GitHub for releases.
AWS Emulator 1.0.322.12026-11-11latest
AWS Emulator 1.0.322.1 (emulator 1.0.322), built 2026-11-12T00:12:33Z.
Images
| Variant | Pull | Immutable tag | Digest |
|---|---|---|---|
| Amazon Linux | docker pull ghcr.io/xsavikx/aws-emulator:1.0.322.1 |
1.0.322.1-20261112.14 |
sha256:150623030d361bed9938b2d71281f3de35f8be9d8ac981f7cfcd85b2fdf8d0fc |
| Debian | docker pull ghcr.io/xsavikx/aws-emulator:1.0.322.1-debian |
1.0.322.1-20261112.14-debian |
sha256:0493ad4c2a2767645b0d188e21c2e3e40db419c28789eb925161be185750044e |
| Distroless | docker pull ghcr.io/xsavikx/aws-emulator:1.0.322.1-distroless |
1.0.322.1-20261112.14-distroless |
sha256:633866eaca6d8f58e345727476da1b800924f81a749468b73de7e1aac546a094 |
The same tags are on docker.io/xsavikx/aws-emulator and quay.io/xsavikx/aws-emulator. Platforms: linux/amd64, linux/arm64.
Upstream changes
215 changes in aws-emulator v1.0.322. The first 15:
- fix: cognito-idp-getuser-refuses-a-revoked-access-token
- fix: iam-10-net-new-behavioral-root-causes-simulateprincipalpolicy
- fix: emr-3-net-new-root-causes-modifyinstancefleet-accepts
- fix: apigatewayv2-deleteportalproduct-performs-no-authorization-so-a-...
- fix: bedrock-agent-deleteflow-stub
- fix: pca-connector-ad-templatearn-validationexception-quotes-the-patt...
- fix: appsync-getschemacreationstatus-stub
- fix: backupsearch-startsearchresultexportjob-event-propagation
- fix: devops-agent-getoperatorapp-missing-agentspace-resourcenotfounde...
- fix: es-legacy-2015-01-01-refusals-diverge-anchored
- fix: lambda-pipes-sqs-2-net-new-causes-a-40c11a
- fix: amplifyuibuilder-gettheme-error-response
- fix: translate-starttexttranslationjob-stub
- fix: iotsitewise-createdatasetexportjob-wrong-behavior
- fix: freetier-upgradeaccountplan-enum-constraint-refusal-lists-accoun...
Verified upstream packages
| File | SHA-256 |
|---|---|
aws-emulator-1.0.322-1-x86_64.rpm |
edbc25a9ebcf7f5acaa15a8d6409bdb4c7de25f3860a69ccfc65f9b01dfec8a0 |
aws-emulator-1.0.322-1-aarch64.rpm |
32ff11c5fe88527e6f647cb99c1011ff594f73d75dad7e7e576ea99bf09e1e55 |
aws-emulator_1.0.322-1_amd64.deb |
ef3c75e5d4196bf2c0170b55b75b01e340e0ef497e636b700a1efe68d68a60d7 |
aws-emulator_1.0.322-1_arm64.deb |
8cfabb461ccfbfa75468393e8dfbf5216b07ef54fcf20584c11d02a9fc854b03 |
Signatures were checked against the AWS package signing key 98BC F336 A3BE 53B7 34E9 67C5 2E5B F49B D940 F624.
Verify
cosign verify ghcr.io/xsavikx/aws-emulator@sha256:150623030d361bed9938b2d71281f3de35f8be9d8ac981f7cfcd85b2fdf8d0fc \
--certificate-identity-regexp '^https://github.com/xSAVIKx/aws-emulator-docker/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comLicenses
The files in this repository are under the Apache License 2.0. The AWS Emulator is under CC0 1.0 Universal, with its vendor/ code under the Apache License 2.0. This is an unofficial community project. It is not affiliated with or endorsed by Amazon Web Services.