Einsteiger5 Min. Lesezeit

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-local

Das 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:

  • -sharedDb hä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 /data plus ein gemountetes Volume schreibt diese Datei auf Platte, die Daten überleben also ein docker 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_REQUEST

Ein 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:8000

Mit 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:

VerhaltenDynamoDB LocalAWS DynamoDB
Abrechnung / RCU / WCUKeinePro Request gemessen
DrosselungNieJa, an Tabellen-/Index-Grenzen
Zeitpunkt der TTL-LöschungBest Effort, kein SLAHintergrundläufe nach AWS-Zeitplan
Auslieferung von DynamoDB StreamsVereinfachtVolle Stream-Semantik + Lambda-Anbindung
Transaktionen über TabellenIn neueren Builds unterstütztVolles ACID mit dokumentierten Grenzen
Global Tables / PITRNicht verfügbarProduktionsfeatures

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:

  1. Unit-Tests — Container in der CI hochfahren, Tabellen in beforeAll anlegen, in afterAll abräumen. Halte Fixtures klein; marshalle schlichtes JSON über den DynamoDB-JSON-Konverter, wenn Tests Attribut-Maps von Hand einfügen.
  2. Integrationstests — nutze dieselbe SDK-Client-Factory wie deine App und tausch nur endpoint und Credentials. Prüfe die Form der Items und Conditional Writes, nicht die verbrauchte Kapazität (Local liefert keine für Budgetierung brauchbare ConsumedCapacity).
  3. 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.

Aktualisiert