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.