Skip to main content

Quick Start

Get ScramDB running in 2 minutes with Docker.

1. Pull and Run​

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

The three ports: 5432 is the PostgreSQL wire protocol, 9090 serves Prometheus metrics, and 9191 is the Semantic AI MCP endpoint for AI agents (see Semantic AI).

The -v scramdb-data:/var/lib/scramdb mount keeps your data across docker stop / docker start and even a docker rm of the container, since it lives in a named Docker volume instead of the container's writable layer.

No authentication by default

The published image's default startup command runs with authentication disabled (--pg-no-auth), listening on all interfaces. Anyone who can reach port 5432 can connect with any username, no password. This is intentional: it makes local development frictionless. It is not safe to expose this container to an untrusted network as-is.

To require passwords, override the container's default 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 \
scramdb/scramdb:latest \
--pg-address 0.0.0.0:5432

With authentication enabled, connections from localhost are still trusted without a password; connections from anywhere else must authenticate with SCRAM-SHA-256. The bootstrap scramdb role has no password set until you give it one:

ALTER ROLE scramdb WITH PASSWORD 'a-real-password';

2. Connect​

Use psql or any PostgreSQL client:

psql -h localhost -p 5432 -U scramdb scramdb

You should see:

scramdb=#

3. Create a Table​

CREATE TABLE sensors (
id BIGINT PRIMARY KEY,
device_id INTEGER NOT NULL,
temperature DOUBLE PRECISION,
humidity DOUBLE PRECISION,
recorded_at TIMESTAMP
);

4. Insert Data​

INSERT INTO sensors VALUES
(1, 101, 22.5, 45.0, '2024-03-15 10:00:00'),
(2, 101, 23.1, 44.0, '2024-03-15 10:05:00'),
(3, 102, 19.8, 55.0, '2024-03-15 10:00:00'),
(4, 102, 20.1, 54.0, '2024-03-15 10:05:00'),
(5, 103, 25.3, 38.0, '2024-03-15 10:00:00');

5. Query​

-- Basic aggregation
SELECT
device_id,
AVG(temperature) AS avg_temp,
MIN(humidity) AS min_humidity,
COUNT(*) AS readings
FROM sensors
GROUP BY device_id
ORDER BY avg_temp DESC;

-- Window function
SELECT
device_id,
recorded_at,
temperature,
temperature - LAG(temperature) OVER (
PARTITION BY device_id ORDER BY recorded_at
) AS temp_change
FROM sensors;

6. Load CSV Data​

COPY ... FROM '/path' reads a file on the server, inside the container, not a file on your machine. Unless you have mounted a matching volume, that path will not exist and the command will fail. For a file that lives on your own machine, use psql's \copy meta-command instead. It streams the file from the client to ScramDB, so no container-side path is needed.

First, create a CSV file on your machine:

cat > sensors.csv <<'EOF'
id,device_id,temperature,humidity,recorded_at
6,101,22.0,46.0,2024-03-15 10:10:00
7,103,24.9,37.5,2024-03-15 10:10:00
EOF

Then, from inside psql, load it:

scramdb=# \copy sensors FROM 'sensors.csv' (FORMAT CSV, HEADER)

If you do mount a volume and want the server to read the file itself, COPY works the same way psql clients expect:

-- Only works if /data/sensors.csv exists inside the container
-- (e.g. add -v $(pwd)/data:/data to your docker run command)
COPY sensors FROM '/data/sensors.csv' (FORMAT CSV, HEADER);

What's Next?​