Prerequisites
Before you run LocalEmu, three things must be in place on
your machine: a recent Python interpreter, the Docker daemon,
and the right pip install
command. This page walks through each one, explains why it
matters, and shows you how to verify it before you move on.
TL;DR: do these three things, in order.
- Install Python 3.10 or newer.
LocalEmu is a Python package. Anything older than 3.10 will
fail at install time with
requires-python >= 3.10. Check withpython3 --version. - Install Docker and start the daemon.
On Mac and Windows that means Docker Desktop. On Linux it
means Docker Engine. Without Docker, the ten container-backed
services (EC2, Lambda, ECS, EKS, RDS, OpenSearch, Redshift,
MQ, MSK, plus VPC networking) cannot run. Everything else
still works in pure Python. Check with
docker ps. - Run the right pip install.
Use
pip install "localemu[runtime]". This installs the package, the full AWS service stack (moto-ext, boto3, botocore), the Athena DuckDB engine, and theawsclibinary (pinned at 1.44.49) that theawsemuwrapper calls under the hood. You do NOT need topip install awscliseparately.
Common pitfall.
Bare pip install localemu
(without the [runtime]
extra) is NOT enough. It installs the package metadata and the
CLI entry-points, but none of the runtime libraries the server
imports at startup. Running
localemu start
afterwards will fail with
ImportError.
Always use the [runtime]
extra unless you have a very specific reason not to.
1. Python 3.10 or newer
LocalEmu's pyproject.toml
declares requires-python = ">=3.10".
The active development target is Python 3.13, but 3.10, 3.11,
and 3.12 all work in production and CI.
$ python3 --version
Python 3.13.12
If the command prints
command not found
or a version older than 3.10, install a recent Python first:
- macOS:
brew install python@3.13, or download from python.org. - Debian / Ubuntu:
sudo apt install python3.13 python3.13-venv. - Fedora / RHEL:
sudo dnf install python3.13.
Always install LocalEmu inside a virtualenv
(python3 -m venv .venv && source .venv/bin/activate)
so its dependencies stay isolated from your system Python.
2. Docker
Docker is required for the ten services whose behavior is
backed by real containers (full list in section 3). The
emulator itself runs on the host as a normal Python process,
but when you call (for example)
RunInstances
the EC2 backend asks the Docker daemon to start a real
container that plays the role of the EC2 instance. No daemon,
no container, no instance. Same story for Lambda invocations,
ECS tasks, RDS engines, and the other seven.
$ docker --version
Docker version 29.4.3, build d600e0e
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
LocalEmu is tested against Docker 24.x and newer. Older
versions may work but are not exercised in CI. The daemon must
be running: docker ps
returns non-zero exit status if it is not.
Install Docker on your platform
- macOS (Intel and Apple Silicon): install Docker Desktop and launch it once so the background daemon starts. Default resource limits (2 CPU, 4 GB RAM) are enough for LocalEmu; bump the RAM if you plan to run EKS, multiple RDS engines, or large user workloads in parallel.
- Linux:
install Docker Engine from your distro or from
docker.com,
then add your user to the
dockergroup sodocker psworks withoutsudo(otherwise LocalEmu, which runs as your user, cannot reach the daemon). - Windows: install Docker Desktop with the WSL2 backend enabled (the default since Docker Desktop 4.x), then run LocalEmu from inside your WSL2 distribution (Ubuntu, Debian, etc.). Native Windows Python is not a supported configuration.
3. What works without Docker
Most of the AWS services LocalEmu emulates are implemented in pure Python and run inside the LocalEmu process itself. Calls to those services succeed even if the Docker daemon is down, absent, or you simply forgot to start it. The ten services in the right-hand column below are the exceptions: they each need a real container to provide real behavior, so they will return errors (or fall back to metadata-only) if Docker is unreachable.
Works without Docker
- S3
- DynamoDB
- SQS
- SNS
- IAM
- STS
- KMS
- Secrets Manager
- SSM Parameter Store
- Step Functions
- CloudFormation
- EventBridge
- EventBridge Scheduler
- Athena (DuckDB backend)
- Glue (metadata)
- API Gateway v1/v2
- ELBv2
- Route 53
- Route 53 Resolver
- CloudWatch
- CloudTrail
- Cognito
- Kinesis (data + Firehose metadata)
- Pipes
- WAFv2
- Batch (metadata)
- VPC metadata APIs
- Transit Gateway
- ACM
- AppSync
- ...and ~80 more
Needs Docker
- EC2: containers act as instances; iptables enforces SG; IMDS sidecar serves 169.254.169.254
- Lambda: function code runs inside the official AWS Lambda runtime images
- ECS: tasks run in real containers on the VPC bridge
- EKS: real Kubernetes via k3d (one container per cluster node)
- RDS: real Postgres / MySQL / MariaDB engines, reachable on a host port
- OpenSearch: real OpenSearch node in a container
- Redshift: real Postgres in Redshift compatibility mode
- MQ: real RabbitMQ broker container
- MSK (Kafka): real apache/kafka KRaft container
- VPC networking: real Docker bridges per VPC for intra-VPC routing and NACL / SG enforcement
If you call
run-instances
without a running Docker daemon, LocalEmu logs a warning and
falls back to a metadata-only response: the EC2 API answers,
but no container starts and you cannot SSH in. To make the
fallback explicit (so you never accidentally trust a "running"
instance that does not exist), set
EC2_VM_MANAGER=none
before starting LocalEmu. The EC2 API still answers Describe /
Run / Terminate calls, but the metadata-only mode is opt-in
and unambiguous.
4. Which pip install do you want?
LocalEmu ships five different install variants (called "extras"
in Python packaging). Each extra is a superset of the previous
one, except for the bare install which is the smallest. Pick
one based on what you plan to do. If you are not sure, the
answer is
[runtime].
| Command | When to use it |
|---|---|
| pip install localemu | Almost never.
Installs only the package metadata and the
localemu /
awsemu /
lpm
CLI entry-points. None of the runtime libraries are
pulled in.
localemu start
fails with
ImportError
immediately.
|
| pip install "localemu[runtime]" | Default choice. Pick this.
Adds the full AWS service stack (moto-ext, boto3,
botocore), the Athena DuckDB engine, antlr parsers,
jinja2, and
awscli 1.44.49.
After this command, both
localemu start
and
awsemu <service> <op>
work out of the box. This is what 99% of users want.
|
| pip install "localemu[test]" |
Everything in
[runtime]
plus pytest, coverage, pika (used by the MQ end-to-end
test), kafka-python (used by the MSK test), aws-cdk-lib,
websocket-client. Pick this only if you plan to run the
LocalEmu test suite locally.
|
| pip install "localemu[dev]" |
Everything in
[test]
plus ruff, mypy, pre-commit, deptry, Cython, networkx,
pypandoc, watchdog. The set of tools LocalEmu
contributors use day to day. Pick this only if you are
modifying the LocalEmu codebase itself.
|
| pip install "localemu[typehint]" |
Everything in
[dev]
plus the full
boto3-stubs
package for every emulated service. Pick this if you
want full IDE autocomplete for boto3 calls while
writing LocalEmu code.
|
The bare install (avoid)
$ pip install localemu
# Installs the package metadata + the localemu / awsemu / lpm
# entry-points, but NOT the runtime stack. ``localemu start``
# will fail with ImportError. Use [runtime] instead. The runtime install (recommended)
$ pip install "localemu[runtime]"
# The one most users want. Brings in:
# - the full AWS service stack (moto-ext, boto3, botocore)
# - awscli (so the awsemu wrapper has something to call)
# - the Athena DuckDB engine, antlr parsers, jinja, etc. The test install
$ pip install "localemu[test]"
# Everything in [runtime] + pytest, coverage, pika (for the MQ
# round-trip), kafka-python (for MSK), aws-cdk-lib. Needed only
# if you plan to run the LocalEmu test suite. The dev install
$ pip install "localemu[dev]"
# Everything in [test] + ruff, mypy, pre-commit, deptry, Cython,
# pypandoc. The set used by LocalEmu contributors. Note on awscli.
The awsemu
CLI that ships with LocalEmu is a thin wrapper that prepends
--endpoint-url=http://localhost:4566
to every command and then shells out to the real
aws
binary. The
[runtime]
extra pins
awscli==1.44.49
as a hard dependency, so the binary is installed for you. You
do not need to run
pip install awscli
separately, and you should not, because LocalEmu pins a
specific version that the wrapper is tested against.
5. The three CLIs LocalEmu ships
Installing
localemu[runtime]
puts three commands on your PATH. Each one has a single, narrow
job. None of them is mandatory in the sense that you must use it,
but they exist to remove friction. Anything they do, you can also
do with the upstream tool directly if you prefer.
| Command | What it does | Do it yourself instead |
|---|---|---|
| localemu |
Starts and controls the LocalEmu server itself.
localemu start
boots all AWS services on
http://localhost:4566;
localemu stop
shuts down and wipes ephemeral state.
| There is no alternative. This is the server. |
| awsemu |
A thin wrapper around the standard
aws
CLI. It prepends
--endpoint-url=http://localhost:4566
to every call and injects example credentials, so you
don't have to set them each time.
awsemu s3 ls
hits LocalEmu, not real AWS.
|
Use the plain
aws
CLI with two environment variables:
export AWS_ENDPOINT_URL=http://localhost:4566
and any AWS credential pair. Your existing scripts,
Terraform configs, and CI pipelines need zero changes,
they just point at LocalEmu via the standard env var.
|
| lpm |
LocalEmu Package Manager. Installs the optional binary
dependencies that two services need to do real work:
ffmpeg
(used by Transcribe to decode media files) and
vosk
(used by Transcribe to run the speech-to-text engine).
Runs on-demand, the first time you call those services,
and caches the result. 99% of users never invoke
lpm
directly.
|
Install
ffmpeg
via Homebrew / apt / dnf, and
vosk
via
pip install vosk.
If both are already on PATH when LocalEmu starts, the
Transcribe service uses them as-is and
lpm
stays out of the way.
|
The pattern.
Each LocalEmu CLI is opt-in convenience around a standard tool
(server / AWS CLI / package install). They exist so that someone
new to LocalEmu can run their first command in 30 seconds without
configuring anything. Once you are comfortable, point your
existing
aws
CLI, boto3 scripts, Terraform, or CDK at
AWS_ENDPOINT_URL=http://localhost:4566
and you never have to think about the wrappers again.
6. Verify the install end-to-end
Three quick commands confirm that all three prerequisites are wired up correctly: Python is the right version, Docker is reachable, and LocalEmu can answer an AWS API call.
$ python3 --version && docker info >/dev/null 2>&1 && pip show localemu >/dev/null && echo READY
Python 3.13.12
READY
$ localemu start
...
Ready.
$ awsemu sts get-caller-identity
{
"UserId": "AKIAIOSFODNN7EXAMPLE",
"Account": "000000000000",
"Arn": "arn:aws:iam::000000000000:root"
} If all three commands succeed, you are ready. Continue to Installation for a full walkthrough, or jump straight to Quick Start and run your first AWS call against the local emulator.
7. Platform notes
macOS (Intel and Apple Silicon)
First-class target. Docker Desktop runs the daemon inside a
Linux VM, which means container bridge IPs are not directly
routable from your Mac. LocalEmu accounts for this: the EIP
data plane binds
127.0.0.1
and tunnels into the container via
docker exec,
so reaching an EC2 instance from the host always works
regardless of the underlying network topology.
Linux (native Docker)
Smoothest path. The Docker daemon and LocalEmu share the same kernel, so container bridge IPs are routable from the host directly. Everything in the EIP, SG, and NACL paths still works through loopback for parity with macOS, so any test or demo you write on Linux behaves the same way on a teammate's Mac.
Windows (WSL2)
Install Docker Desktop with the WSL2 backend enabled, then run LocalEmu from inside your WSL2 distribution (not from PowerShell or cmd). Native Windows Python is not a supported configuration. From inside WSL2, treat the rest of these docs as Linux instructions: the same commands work unchanged.