DynamoDB Local mit Docker betreiben — der komplette Guide
DynamoDB Local ist die herunterladbare Emulation von DynamoDB in einem einzigen Prozess — gleiche API, kein AWS-Konto, kein Netzwerk, keine Rechnung pro Request. Nimm es für lokale Entwicklung und Integrationstests und richte denselben Code in Produktion auf die Cloud. Es ignoriert provisionierten Durchsatz und drosselt nie, kann also für Last- oder Limit-Tests nicht einspringen.
Wie starte ich DynamoDB Local mit Docker?
Mit docker run -p 8000:8000 amazon/dynamodb-local startest du das offizielle Image,
das die DynamoDB-Engine unter http://localhost:8000 bereitstellt. Richte dein AWS SDK oder
die CLI mit beliebigen Dummy-Credentials auf diesen Endpoint, dann legst du Tabellen an und
schickst Requests genauso wie gegen die Cloud. Ergänze -sharedDb und ein gemountetes
-dbPath-Volume, damit die Daten Neustarts überleben.
Den Container starten
docker run -p 8000:8000 amazon/dynamodb-localDas stellt die Engine unter http://localhost:8000 bereit.
docker-compose
Die meisten Projekte nageln das in docker-compose.yml fest, damit das ganze Team denselben
Endpoint bekommt:
services:
dynamodb:
image: amazon/dynamodb-local
user: root
command: '-jar DynamoDBLocal.jar -sharedDb -dbPath /data'
ports:
- '8000:8000'
volumes:
- dynamodb-data:/data
volumes:
dynamodb-data:Das Image läuft als der Nicht-Root-Nutzer dynamodblocal, der keine Datenbankdatei in einem
root-eigenen benannten Volume öffnen kann — ohne user: root landest du bei
SQLiteException [14] unable to open database file, und jeder Aufruf hängt.
Persistenz
Standardmäßig läuft DynamoDB Local im Speicher — jede Tabelle verschwindet, sobald der Container stoppt. Zwei Flags machen es dauerhaft:
-sharedDbhält alle Clients auf einer gemeinsamen Datenbankdatei (ohne das bekommt jede Kombination aus Credentials und Region ihre eigene isolierte DB — die verbreitete Überraschung „wo ist meine Tabelle hin?").-dbPath /dataplus ein gemountetes Volume schreibt diese Datei auf Platte, die Daten überleben also eindocker compose down.
Das SDK darauf zeigen lassen
Nur der Endpoint ändert sich — die Credentials dürfen beliebige Dummy-Werte sein:
import {DynamoDBClient} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({
endpoint: 'http://localhost:8000',
region: 'local',
credentials: {accessKeyId: 'x', secretAccessKey: 'x'}
});Eine Tabelle anlegen
aws dynamodb create-table \
--endpoint-url http://localhost:8000 \
--table-name AppData \
--attribute-definitions AttributeName=PK,AttributeType=S AttributeName=SK,AttributeType=S \
--key-schema AttributeName=PK,KeyType=HASH AttributeName=SK,KeyType=RANGE \
--billing-mode PAY_PER_REQUESTEin PK/SK-Schema im Stil von Single-Table Design ist
eine gute Vorgabe. Wenn du Fixtures lädst, wandle schlichtes JSON mit dem
DynamoDB-JSON-Konverter ins Wire-Format.
Prüf, ob der Container läuft und die Tabelle angekommen ist:
aws dynamodb list-tables --endpoint-url http://localhost:8000Mit einer GUI durchsehen
CLI-Aufrufe werden schnell mühsam. Die üblichen Optionen sind die Open-Source-Web-UI
dynamodb-admin oder ein Desktop-Client. DynoTable verbindet sich direkt mit
localhost:8000 (oder mit jedem LocalStack-Endpoint — siehe
Verbindung zu DynamoDB Local & LocalStack)
und lässt dich lokale Tabellen durchsuchen, mit der abfragen und bearbeiten —
mit derselben Oberfläche wie bei Cloud-Tabellen, ohne Umwege über die aws-CLI.
Was Local nicht emuliert
Behandle Local als API-Kompatibilitätsschicht, nicht als Kapazitätssimulator. Es ignoriert
provisionierten Durchsatz, liefert nie eine
ProvisionedThroughputExceededException
und bildet das Burst-Verhalten von On-Demand nicht ab. Ein Lasttest gegen Local sagt dir
nichts über Partitionsgrenzen oder Adaptive Capacity in AWS.
Weitere Lücken zeigen sich in Integrationstests, wenn du nicht mit ihnen rechnest:
| Verhalten | DynamoDB Local | AWS DynamoDB |
|---|---|---|
| Abrechnung / RCU / WCU | Keine | Pro Request gemessen |
| Drosselung | Nie | Ja, an Tabellen-/Index-Grenzen |
| Zeitpunkt der TTL-Löschung | Best Effort, kein SLA | Hintergrundläufe nach AWS-Zeitplan |
| Auslieferung von DynamoDB Streams | Vereinfacht | Volle Stream-Semantik + Lambda-Anbindung |
| Transaktionen über Tabellen | In neueren Builds unterstützt | Volles ACID mit dokumentierten Grenzen |
| Global Tables / PITR | Nicht verfügbar | Produktionsfeatures |
Wenn dein Test auf Drosselung, TTL-Ablauf innerhalb von Sekunden oder Stream-Fan-out prüft, lass mindestens eine Suite gegen eine Wegwerf-Tabelle in der Cloud oder gegen LocalStack mit den nötigen Features laufen.
Ein praxistauglicher lokaler Workflow
Die meisten Teams binden Local auf drei Ebenen ein:
- Unit-Tests — Container in der CI hochfahren, Tabellen in
beforeAllanlegen, inafterAllabräumen. Halte Fixtures klein; marshalle schlichtes JSON über den DynamoDB-JSON-Konverter, wenn Tests Attribut-Maps von Hand einfügen. - Integrationstests — nutze dieselbe SDK-Client-Factory wie deine App und tausch nur
endpointund Credentials. Prüfe die Form der Items und Conditional Writes, nicht die verbrauchte Kapazität (Local liefert keine für Budgetierung brauchbareConsumedCapacity). - Manuelles Erkunden — verbinde DynoTable mit einem Local-Profil, stage Änderungen und lass PartiQL- oder Key-Condition-Abfragen laufen, bevor du Schemaänderungen ausrollst.
Wenn dir ein einzelner Prozess zu klein wird — mehrere Services, S3-Trigger oder IAM-artiges Routing —, steig auf LocalStack oder ein Dev-Konto um. Local bleibt die schnellste Schleife für „kompiliert mein Zugriffsmuster?"
Daten seeden, ohne von Hand zu marshallen
Zehn Fixture-Items aus einer JSON-Datei zu laden geht schneller, wenn du nicht jeden Wert
selbst taggst. Füg das Array in den
DynamoDB-JSON-Konverter ein, kopier die marshallte Ausgabe
und schreib sie per BatchWriteItem gegen --endpoint-url http://localhost:8000. Für update-lastige Fixtures setzt du die
UpdateExpression im
DynamoDB Expression Builder zusammen und fügst die
erzeugten Attribut-Maps in dein Test-Harness ein.
Der Item-Editor von DynoTable macht dasselbe Marshalling beim Commit — praktisch, wenn dich
ein fehlgeschlagener Test mit rohen {"S":...}-Blobs in der CLI zurücklässt.
Wann du Local verlässt
Geh auf eine echte Tabelle, sobald du eines der folgenden Dinge auf AWS selbst messen musst:
- Kapazitätsplanung — ein 1 KB großes Item, 1.000-mal pro Sekunde abgefragt, verbraucht bei On-Demand-Abrechnung grob 250 letztendlich konsistente RCU pro Sekunde; Local meldet null. Modellier das im Preisrechner mit Größen aus dem Item-Size-Rechner.
- Verzögerung der Index-Propagierung — GSI-Reads sind in Produktion letztendlich konsistent; Local liefert Index-Zeilen so schnell zurück, dass Stale-Read-Bugs sich bis zum Deploy verstecken.
- Kontoübergreifendes IAM — ressourcengebundene Rollen und Condition Keys gibt es nur in der Cloud.
Behalte Local für schnelles Feedback zu Schema und Expression-Syntax; validier Annahmen zu Kosten und Konsistenz gegen eine Staging-Tabelle, bevor Produktions-Traffic kommt.
Fallstricke, um die du herumskripten solltest
- Vergessenes
-sharedDb— jedes eigene Credential-Paar bekommt eine isolierte Datenbank; CI und dein Laptop sehen aus wie zwei verschiedene Universen. - Root-eigenes Volume ohne
user: root— das SQLite-Backend scheitert lautlos, bis du das Compose-Override aus dem Abschnitt oben ergänzt. - Streams-Parität annehmen — Lambdas an Streams brauchen ein Ziel in der Cloud oder in LocalStack; Local allein übt kein Fan-out.
- Leere Strings als Schlüssel — auf Nicht-Schlüssel-Attributen seit 2020 erlaubt, auf Schlüsseln weiterhin abgelehnt; validier Fixtures genauso wie in AWS.
Lade DynoTable herunter, leg ein Profil an, das auf http://localhost:8000 zeigt,
und durchsuch die Tabellen, die du gerade angelegt hast — dasselbe Grid, derselbe Filter-Builder
und dieselbe SQL Workbench wie in Produktion, ganz ohne AWS-Ausgaben in der Schleife.