Docker Deployment
ScramDB ships as a single Docker image that runs both single-node and cluster deployments. This page covers running one node. For a multi-node cluster, see Clustering (requires an Enterprise license).
Quick Startβ
docker pull scramdb/scramdb:latest
docker run -d \
--name scramdb \
-p 5432:5432 \
-p 9090:9090 \
-p 9191:9191 \
-v scramdb-data:/var/lib/scramdb \
scramdb/scramdb:latest
Connect with any PostgreSQL client:
psql "host=127.0.0.1 port=5432 user=scramdb dbname=scramdb"
Port 5432 is the PostgreSQL wire protocol port, and 9090 serves Prometheus metrics at /metrics and a plain health check at /health.
Securing a nodeβ
The published image's container command is --pg-address 0.0.0.0:5432 --pg-no-auth. That last flag trusts every incoming connection with no password check, and it also disables hba_file-based rules. This is intentional for a fast local start, but it means the container listens on every interface with no authentication until you change it.
The engine itself does not default this way: with no flags and no config file, ScramDB binds to 127.0.0.1:5432 only and authentication is on. The 0.0.0.0 bind and the disabled auth both come from the image's own startup command, not from the engine.
To run with authentication in Docker, override the container command and drop --pg-no-auth:
docker run -d \
--name scramdb \
-p 5432:5432 \
-p 9090:9090 \
-p 9191:9191 \
-v scramdb-data:/var/lib/scramdb \
-v $(pwd)/scramdb.toml:/etc/scramdb/config.toml:ro \
scramdb/scramdb:latest \
--config /etc/scramdb/config.toml --pg-address 0.0.0.0:5432
With --pg-no-auth absent, ScramDB uses its built-in rules by default: connections from localhost are trusted, everything else requires a password. To use your own rules, point hba_file at a mounted pg_hba.conf-style file. To add TLS, set tls_cert and tls_key to mounted PEM files. All three keys live under [general]:
[general]
pg_address = "0.0.0.0:5432"
hba_file = "/etc/scramdb/pg_hba.conf"
tls_cert = "/etc/scramdb/server.crt"
tls_key = "/etc/scramdb/server.key"
There is no environment variable or CLI flag that turns authentication on; it is on by default and only --pg-no-auth (or pg_no_auth = true in the config) turns it off.
Configurationβ
ScramDB is configured with a TOML file. The image ships a working single-node configuration, so no file is required to get started. To customize a node, mount your own configuration and point the container at it:
docker run -d \
--name scramdb \
-p 5432:5432 \
-p 9090:9090 \
-p 9191:9191 \
-v scramdb-data:/var/lib/scramdb \
-v $(pwd)/scramdb.toml:/etc/scramdb/config.toml:ro \
scramdb/scramdb:latest
A minimal configuration file:
[general]
pg_address = "0.0.0.0:5432"
metrics_port = 9090
jit_enabled = true
[storage]
prod_name = "tundra"
shard_id = 0
basedir = "/var/lib/scramdb"
buffer_pool_percent = 60
execution_memory_percent = 15
buffer_pool_percent and execution_memory_percent size the buffer pool and query execution memory as a share of the RAM ScramDB detects (see the note on container-aware sizing below). You can pin an exact size instead with buffer_pool_size_bytes = "2GB".
If you don't need to change anything under [general], mounting your own file for [storage] tuning alone is fine; every field not set falls back to its default.
See Single Node for sizing guidance and Requirements for hardware.
Environment variablesβ
The container reads a handful of environment variables directly; all other tuning lives in the configuration file.
| Variable | Default | Description |
|---|---|---|
SCRAMDB_LOG | info | Log level: off, trace, debug, info, warn, or error. An unrecognized value silently falls back to info. |
SCRAMDB_LOG_FORMAT | text | Set to json for structured JSON logs |
SCRAMDB_LICENSE_KEY | unset (Community) | Enterprise or Trial license key. Required to enable clustering; also available as license_key under [general] in the config file. The environment variable wins if both are set. |
SCRAMDB_GPU_FORCE | unset (false) | Set to 1 or true to force GPU acceleration on |
Cluster mode is selected by three additional variables (NODE_NAME, ADVERTISE_ADDR, and SEEDS), read by the container's entrypoint script rather than the engine itself, plus two optional geo-placement variables (REGION and ZONE) the same script renders straight into the node's config. See Clustering.
GPU accelerationβ
[gpu] enabled = true is the shipped default, and it is safe with no GPU hardware at all: on a plain cloud VM or a laptop with no device, ScramDB detects that no GPU is present, logs one line, and falls back to CPU execution. Nothing extra needs to be mounted or added.
If a GPU is passed through to the container, ScramDB pins host memory on demand for GPU transfers. If the container's capability set already allows that (a Kubernetes pod without a capability drop, or a container that already has CAP_IPC_LOCK), nothing further is needed. If it doesn't, ScramDB automatically falls back to a pre-allocated pinned memory pool (256 MB by default, [gpu] pinned_memory_pool) at startup and keeps running: GPU queries still execute, with one extra memory copy per transfer instead of a zero-copy path.
You only need to act if you see a GPU memory-pinning error in the logs, which happens only when the pinned pool itself fails to allocate. The fix is one of:
# Option 1: raise the pinned pool
[gpu]
pinned_memory_pool = "512MB"
# Option 2: grant the capability for a zero-copy path
docker run --cap-add=IPC_LOCK ...
No other Docker capability, --privileged flag, or --shm-size setting is needed for GPU acceleration in any configuration.
Volumesβ
Mount a persistent volume at /var/lib/scramdb so your data survives restarts and upgrades. It holds both the columnar storage and the write-ahead log.
docker volume create scramdb-data
docker run -d \
--name scramdb \
-p 5432:5432 \
-v scramdb-data:/var/lib/scramdb \
scramdb/scramdb:latest
The shipped image also archives the write-ahead log by default ([storage.wal.archive] enabled = true), writing to a wal-archive subdirectory inside the data volume so point-in-time recovery works out of the box with no extra setup. See Backup and restore for the CLI that reads it.
Resource limitsβ
Bound the container's CPU and memory with the standard Docker flags:
docker run -d \
--name scramdb \
-p 5432:5432 \
-p 9090:9090 \
-p 9191:9191 \
-v scramdb-data:/var/lib/scramdb \
--cpuset-cpus="0-7" \
--memory=16g \
scramdb/scramdb:latest
--cpuset-cpus is preferred: an exclusive cpuset pins ScramDB to specific cores with no CFS throttling jitter, while --cpus (a quota, shown below) now also resolves to the correct worker count but shares physical cores under CFS scheduling. See Parallelism for exactly how each resolves into a worker count and for the SCRAMDB_MAX_CORES override.
docker run -d \
--name scramdb \
-p 5432:5432 \
-p 9090:9090 \
-p 9191:9191 \
-v scramdb-data:/var/lib/scramdb \
--cpus=8 \
--memory=16g \
scramdb/scramdb:latest
ScramDB reads the container's own cgroup memory limit (falling back to host memory if none is set) and sizes the buffer pool and execution memory pools from it automatically when you use the percent-based keys (buffer_pool_percent, execution_memory_percent); pinning exact byte sizes in the config file is for when you want a fixed budget regardless of the container limit.
Docker Composeβ
Single node:
services:
scramdb:
image: scramdb/scramdb:latest
ports:
- "5432:5432" # PostgreSQL clients
- "9090:9090" # Prometheus metrics and health
volumes:
- scramdb-data:/var/lib/scramdb
deploy:
resources:
limits:
cpus: '8'
memory: 16G
volumes:
scramdb-data:
For a multi-node Compose file, see Clustering.
Health Checkβ
The image includes a built-in health check using pg_isready:
pg_isready -h 127.0.0.1 -p 5432 -U scramdb -d scramdb
The metrics server also exposes a plain HTTP health endpoint, useful for a load balancer or a Kubernetes httpGet probe that shouldn't need a PostgreSQL client:
curl http://127.0.0.1:9090/health
# ok