Running Dynamodb local with Docker and Persistent Data Storage

I'm working on a project that is using Dynamodb as the primary database.  I haven't used dynamodb local before and wanted to take it for a spin.

Amazon distributes a Docker image and the setup was fairly painless.  The docker-compose section of my docker-compose.yml became

version: "3"
services:
  dynamodb-local:
    image: dynamo:latest    
    
    command: "-jar DynamoDBLocal.jar -sharedDb -dbPath /home/dynamodblocal/data"
    restart: always
    volumes:
      - dynamodb-data:/home/dynamodblocal/data
    ports:
      - "8000:8000"
    networks:
      - app_network  

  app:    
    ports:
      - "3000:3000"
    depends_on:
      - redis
      - dynamodb-local
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./:/app
      - /app/node_modules
      - /app/.next
    networks:
      - app_network          

networks:
  app_network:  

volumes:  
  dynamodb-data:
    external: true

The docker command that i initially found was docker run -p 8000:8000 amazon/dynamodb-local.  This will start the dynamodb-local instance but doesn't include a volume for persistent storage.

The major headache I experienced was a SQLite error that the database file could not be opened.  No matter what I tried, dynamodb wouldn't work when I added -dbPath /home/dynamodblocal/data.

After a lot of googling the issue seemed to be a permission error.  Seemed like a weird error, and at first I didn't think it was correct -— wouldn't Amazon had handled this use case already with the docker image???

Well, apparently the answer is no.  The problem ended up being that the dynamodb process is being run by the dynamodblocal user and the /data volume was being created and owned by root.  The easiest solution is to build your own docker image and create the folder that will be used for the docker volume.  These commands are executed as the dynamodblocal user so the permissions will not conflict.

FROM amazon/dynamodb-local:latest

WORKDIR /home/dynamodblocal

RUN mkdir data

The only additional caveat is that dynamodb local creates tables in the localhost region, so to connect with aws-sdk you need to update your init to

const db = new AWS.DynamoDB.DocumentClient({
  apiVersion: "2012-08-10",
  endpoint: "http://dynamodb-local:8000",
  region: "localhost",
});

You'll notice that the endpoint is http://dynamodb-local:8000.  If you're not familiar with docker-compose it has a really cool feature of mapping a network name to the service name.  So, anywhere in my app I can reference https://dynamodb-local and the request will be forwarded to the dynamodb-local instance.

Happy coding.