DocumentDB Local
DocumentDB Local provides a lightweight, containerized environment for developing and testing applications locally, including prototyping and integration testing.
The examples below use the PostgreSQL 17 image from release 0.117.0. Other PostgreSQL major versions and image tags are listed in the 0.117 release.
Get the Docker container image using docker pull.
docker pull ghcr.io/documentdb/documentdb/documentdb-local:pg17-0.117.0
To run the container, use docker run. Afterwards, use docker ps to validate that the container is running.
read -r -p 'DocumentDB username: ' DOCUMENTDB_USERNAME
read -r -s -p 'DocumentDB password: ' DOCUMENTDB_PASSWORD
printf '\n'
export DOCUMENTDB_USERNAME DOCUMENTDB_PASSWORD
docker run -dt -p 127.0.0.1:10260:10260 --name docdb \
ghcr.io/documentdb/documentdb/documentdb-local:pg17-0.117.0 \
--username "${DOCUMENTDB_USERNAME:?DocumentDB username cannot be empty}" \
--password "${DOCUMENTDB_PASSWORD:?DocumentDB password cannot be empty}"
docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5aff734a3591 ghcr.io/documentdb/documentdb/documentdb-local:pg17-0.117.0 "/bin/bash -c '/home…" 5 seconds ago Up 4 seconds 127.0.0.1:10260->10260/tcp docdbThe prompts export the credentials for the later client examples, and the guards
prevent an empty value from falling through to the image's public defaults. If you
open a new shell, set both variables again. The loopback binding makes the gateway
reachable only from this host. To allow remote clients, change it to
-p 10260:10260 only after restricting the port with a firewall and configuring a
certificate that remote clients can validate.
This container writes its database to /data, which the image declares as a Docker volume. The command above mounts nothing there, so each docker run gets a fresh anonymous volume: the data does not survive re-creating the container, and the old volume is left behind on the host until you prune it. Mount a named volume - -v documentdb-data:/data - to persist it. See --data-path in the table below.
docker ps reports the container as Up well before DocumentDB can accept connections - PostgreSQL has to initialize, the extensions have to be set up, and the admin user has to be created first. Connecting too early fails with MongoServerSelectionError or ECONNREFUSED.
The entrypoint prints a ready banner after gateway startup and any requested data initialization finish. Wait for it before connecting:
until docker logs docdb 2>&1 | grep -q "=== DocumentDB is ready ==="; do sleep 2; doneFirst start typically takes a few tens of seconds. If the command has not returned after a couple of minutes, the container most likely exited during startup - interrupt it and check docker ps -a and docker logs docdb for the error.
Use docker logs docdb rather than docker logs -f docdb to check readiness. The container streams the PostgreSQL, gateway, and entrypoint logs to stdout for its whole lifetime, so -f never returns.
The DocumentDB gateway endpoint is available on port 10260 by default. To access this with mongosh, run:
mongosh localhost:10260 \
-u "${DOCUMENTDB_USERNAME:?Set DOCUMENTDB_USERNAME first}" \
-p "${DOCUMENTDB_PASSWORD:?Set DOCUMENTDB_PASSWORD first}" \
--authenticationMechanism SCRAM-SHA-256 \
--tls --tlsAllowInvalidCertificatesCurrent Mongosh Log ID: 690cdcb84e2e610f0f48e609
Connecting to: mongodb://<credentials>@localhost:10260/?tls=true&tlsAllowInvalidCertificates=true&directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.5.1
Using MongoDB: 7.0.0
Using Mongosh: 2.5.1
mongosh 2.5.9 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
[direct: mongos] test>The following table summarizes the available Docker commands for configuring the emulator. This table details the corresponding arguments, environment variables, allowed values, default settings, and descriptions of each command.
| Requirement | Arg | Env | Allowed values | Default | Description |
|---|---|---|---|---|---|
| Print the settings to stdout from the container | --help, -h | N/A | N/A | N/A | Display information on available configuration |
| Specify the username for DocumentDB. | --username [value] | Overrides USERNAME environment variable | STRING | default_user | Username for DocumentDB. It may not be an internal DocumentDB role name, and it may not begin with documentdb, citus, pg, or internal_role (case-insensitive). The container rejects a reserved name and exits before starting anything. |
| Specify the password for DocumentDB. | --password [value] | Overrides PASSWORD environment variable | STRING | Admin100 | Password for DocumentDB. Always set this explicitly. The built-in default is well known, and anyone who can reach the published port can authenticate with it. |
| The port of the DocumentDB endpoint. | --documentdb-port [value] | Overrides DOCUMENTDB_PORT environment variable | INT | 10260 | The port needs to be published. For local use, bind only to loopback - for example, -p 127.0.0.1:10260:10260. To use host port 27017 without changing the gateway port, publish -p 127.0.0.1:27017:10260; add --documentdb-port 27017 only when changing the container-side port too. |
| Specify a directory for data. | --data-path [value] | Overrides DATA_PATH environment variable. | STRING | /data | Data is not persisted unless you mount a volume at this path - for example, -v documentdb-data:/data. To use a different directory, set the mount and the flag together, keeping in mind that they go on opposite sides of the image name: -v / --mount is a docker run option and comes before it, --data-path is a container argument and comes after it. See the example below the table. |
| Specify the owner. | --owner [value] | Overrides OWNER environment variable. | STRING | documentdb | The PostgreSQL role used to create the admin user. The cluster this image initializes has a single superuser role, documentdb, so leave this at the default: any other value fails with role "<value>" does not exist after PostgreSQL has already initialized, and the container exits. |
| Specify whether to start the PostgreSQL server. | --start-pg [value] | Overrides START_POSTGRESQL environment variable | true, false | true | Set this to false only when you are pointing the gateway at a PostgreSQL server you run yourself; the container then expects one to be reachable on --pg-port. |
| Specify whether to create a user. | --create-user [value] | Overrides CREATE_USER environment variable | true, false | true | With false the container starts the gateway without creating the admin user. Nothing can authenticate with --username / --password until you create a user yourself, and data initialization fails if you enabled it. |
| Specify the port for the PostgreSQL server. | --pg-port [value] | Overrides POSTGRESQL_PORT environment variable | INT | 9712 | Specify the port for the PostgreSQL server. |
| Specify whether to allow external connections to PostgreSQL. | --allow-external-connections [value] | Overrides ALLOW_EXTERNAL_CONNECTIONS environment variable | true, false | false | Opens the container's internal PostgreSQL server to all interfaces and adds a permissive host-based authentication rule (host all all 0.0.0.0/0 scram-sha-256), which lets any role reach any database from any address with a password. It only changes configuration inside the container, so you also need to publish the PostgreSQL port - for example -p 9712:9712 - to connect from the host. Ignored when --start-pg false. This does not affect the gateway, which always listens on all interfaces on the DocumentDB port. |
| Specify the path to a certificate for securing traffic. | --cert-path [value] | Overrides CERT_PATH environment variable. | STRING | NA | PEM-format certificate. Must be set together with --key-file - setting only one of the two fails at startup. You need to mount this file into the container. For example, to set /mycert.pem, add this option to docker run command: --mount type=bind,source=./mycert.pem,target=/mycert.pem. |
| Override default key with key in key file. | --key-file [value] | Overrides KEY_FILE environment variable. | STRING | NA | PEM-format private key. Must be set together with --cert-path - setting only one of the two fails at startup. You need to mount this file into the container. For example, to set /mykey.key, add this option to docker run command: --mount type=bind,source=./mykey.key,target=/mykey.key |
| Set the TLS mode for client connections. | --tlsMode [value] | Overrides TLS_MODE environment variable | disabled, allowTLS, requireTLS | allowTLS | With allowTLS the gateway accepts both plain and TLS connections; disabled behaves the same way. requireTLS rejects plain connections, so every client must connect with tls=true. |
| Enable initialization with built-in sample data. | --init-data [value] | Overrides INIT_DATA environment variable | true, false | false | Loads the StoreData dataset once per fresh data volume. Use a new, empty volume to seed again; see Built-in sample data. |
| Specify a directory of scripts for database initialization. | --init-data-path [value] | Overrides INIT_DATA_PATH environment variable | STRING | /init_doc_db.d | JavaScript files run alphabetically using mongosh, once per fresh data volume. Syntax or runtime errors abort initialization. An attempted script run is not repeated on restart, so fix the scripts and use a fresh volume to retry. |
| Skip initialization with built-in sample data. | --skip-init-data | Overrides SKIP_INIT_DATA environment variable | true, false (SKIP_INIT_DATA only - the flag itself takes no value) | N/A | Legacy alias for --init-data false. Note that SKIP_INIT_DATA=false does the opposite of the flag: with INIT_DATA unset it enables the built-in sample data. Does not affect --init-data-path. |
| Disable the use of extended RUM for indexes. | --disable-extended-rum | Overrides DISABLE_EXTENDED_RUM environment variable | N/A (takes no value) | N/A | Extended RUM is enabled by default. Known issue: this flag does not currently disable it - the container still starts with documentdb_extended_rum configured. |
| Enable telemetry data. | --enable-telemetry [value] | Overrides ENABLE_TELEMETRY environment variable | true, false | false | Known issue: the value is validated at startup but no telemetry is currently emitted - the gateway's metrics and tracing exporters are disabled in this image, and an invalid value only serves to abort startup. |
| Specify log verbosity. | --log-level [value] | Overrides LOG_LEVEL environment variable. | quiet, error, warn, info, debug, trace | info | Known issue: the value is validated at startup but does not currently change what the container logs. To change the gateway's own verbosity, set the DOCUMENTDB_LOG_LEVEL environment variable instead; it takes a tracing filter such as info or debug (quiet is not one of its values). |
--skip-init-data and --disable-extended-rum are the only options that take no value. Passing one anyway - for example --disable-extended-rum false - is rejected as an unexpected argument and the container exits.
A complete docker run showing where each kind of option goes - Docker options before the image name, container arguments after it. This is the command from the Running section above with a persistent volume and sample data added, so remove that container first with docker rm -f docdb:
docker run -dt \
-p 127.0.0.1:10260:10260 \
-v documentdb-data:/data \
--name docdb \
ghcr.io/documentdb/documentdb/documentdb-local:pg17-0.117.0 \
--username "${DOCUMENTDB_USERNAME:?Set DOCUMENTDB_USERNAME first}" \
--password "${DOCUMENTDB_PASSWORD:?Set DOCUMENTDB_PASSWORD first}" \
--init-data trueRelease 0.117 replaces the earlier small sampledb seed with the complete StoreData dataset. Loading remains opt-in: add --init-data true to the container arguments, as in the example above.
| Collection | Documents |
|---|---|
StoreData.stores | 41,505 |
StoreData.ratings | 2 |
The bundled Extended JSON preserves BSON Binary, Date, and Timestamp values. After the ready banner, inspect the collections with mongosh:
db.getSiblingDB("StoreData").stores.countDocuments({}) // 41505
db.getSiblingDB("StoreData").ratings.countDocuments({}) // 2Seeding remains one-shot per data volume. Previously seeded volumes are not automatically migrated to StoreData; use a new, empty volume when you want the new sample dataset. A direct loader rerun tolerates duplicate keys rather than duplicating documents. See the versioned sample-data guide for manual loader instructions.
The latest tag is a convenience alias. Pin an explicit tag for anything reproducible:
| Tag | Contents |
|---|---|
ghcr.io/documentdb/documentdb/documentdb-local:pg18-0.117.0 | DocumentDB 0.117.0 on PostgreSQL 18 |
…:pg17-0.117.0 | DocumentDB 0.117.0 on PostgreSQL 17 |
…:pg16-0.117.0 · …:pg15-0.117.0 | PostgreSQL 16 and 15 |
…:latest | Currently identical to pg17-0.117.0 |
latest tracks PostgreSQL 17, while the documentdb package on Linux pins
PostgreSQL 18. If you evaluate in Docker and then deploy from packages, you change
major version unless you pin the tag deliberately.
Every image records what it was built from:
docker run --rm --entrypoint cat ghcr.io/documentdb/documentdb/documentdb-local:pg18-0.117.0 /version.txtDocumentDB Local starts empty. Pass --init-data true to seed the StoreData database
with the stores and ratings collections:
docker run -dt -p 127.0.0.1:10260:10260 --name documentdb \
ghcr.io/documentdb/documentdb/documentdb-local:latest \
--username '<YOUR_USERNAME>' --password '<YOUR_PASSWORD>' --init-data trueSeeding happens once per data volume, on a fresh volume. Existing volumes are not migrated automatically; re-create the volume to seed again.
| Requirement | Arg | Env | Default | Description |
|---|---|---|---|---|
| Load built-in sample data | --init-data [true|false] | INIT_DATA | false | Seed the StoreData sample collections on a fresh data volume. |
| Skip built-in sample data | --skip-init-data | SKIP_INIT_DATA | — | Legacy alias for --init-data false. Does not affect --init-data-path. |
| Run custom initialization scripts | --init-data-path [PATH] | INIT_DATA_PATH | /init_doc_db.d | Execute every .js file in the mounted directory with mongosh. |
The built-in sample dataset currently includes 41,505 store documents and 2 rating documents.
docker run -dt --name documentdb \
-p 127.0.0.1:10260:10260 \
-v /path/to/init/scripts:/init_doc_db.d \
ghcr.io/documentdb/documentdb/documentdb-local:latest \
--username '<YOUR_USERNAME>' \
--password '<YOUR_PASSWORD>' \
--init-data-path /init_doc_db.dWhen --init-data-path is provided, DocumentDB Local skips the built-in sample data
and runs only the scripts you mounted.
If you do not supply your own certificate with --cert-path and --key-file, DocumentDB Local generates a self-signed certificate on first start and reuses it on subsequent starts of the same container, so docker stop / docker start keeps it stable. Removing and re-creating the container generates a new certificate unless you persist the directory it is stored in. The generated certificate is valid for 365 days and is not renewed automatically - re-create the container, or delete cert.pem from the state directory shown below, to generate a fresh one.
To validate the certificate instead of skipping validation with tlsAllowInvalidCertificates=true, copy it out of the container and point mongosh at it.
The gateway picks its TLS state directory from the first writable candidate. In this image that resolves to a path under the container user's home directory, so no extra options are needed when starting the container. In a bash window, copy the certificate from the container to the local host:
docker cp docdb:/home/documentdb/.local/state/documentdb-gateway/tls/cert.pem ~/documentdb-cert.pemThe gateway logs the path it actually chose on startup. Check there first if the copy reports No such container:path:
docker logs docdb | grep "TLS auto-gen"To keep the same certificate across re-creating the container, pin the location with DOCUMENTDB_TLS_STATE_DIR and put it inside the data volume. This replaces the container you started earlier, so run docker rm -f docdb first:
docker run -dt \
-p 127.0.0.1:10260:10260 \
-v documentdb-data:/data \
-e DOCUMENTDB_TLS_STATE_DIR=/data/tls \
--name docdb \
ghcr.io/documentdb/documentdb/documentdb-local:pg17-0.117.0 \
--username "${DOCUMENTDB_USERNAME:?Set DOCUMENTDB_USERNAME first}" \
--password "${DOCUMENTDB_PASSWORD:?Set DOCUMENTDB_PASSWORD first}"Point it inside the data directory rather than at a volume of its own: the entrypoint takes ownership of the data directory on every start, whereas a separate volume is created root-owned and the gateway - which runs as an unprivileged user - cannot write its key there. The trade-off is that the same step runs chmod -R 750 over that directory, so from the second start onwards the private key is group-readable rather than owner-only, and it is included in any backup of the data volume.
mongosh localhost:10260 \
-u "${DOCUMENTDB_USERNAME:?Set DOCUMENTDB_USERNAME first}" \
-p "${DOCUMENTDB_PASSWORD:?Set DOCUMENTDB_PASSWORD first}" \
--authenticationMechanism SCRAM-SHA-256 \
--tls --tlsCAFile ~/documentdb-cert.pemCurrent Mongosh Log ID: 690ce1171181053c6edbf354
Connecting to: mongodb://<credentials>@localhost:10260/?directConnection=true&serverSelectionTimeoutMS=2000&authMechanism=SCRAM-SHA-256&tls=true&tlsCAFile=%2Fhome%2Fuser%2Fdocumentdb-cert.pem&appName=mongosh+2.5.1
Using MongoDB: 7.0.0
Using Mongosh: 2.5.1
mongosh 2.5.9 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/
[direct: mongos] test>DocumentDB Local runs a single container on one machine, with no replication and no failover, which is what makes it convenient for development and testing. For other ways to run DocumentDB:
If you encounter issues with using this version of DocumentDB, open an issue in the GitHub repository (https://github.com/documentdb/documentdb/issues) and tag it with the label documentdb-local.