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.
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?β
- First Queries - More SQL examples with joins, subqueries, and session settings
- SQL Reference - Full SQL compatibility reference
- Data Types - PostgreSQL type mapping
- Clients and Drivers - Connect from your language's standard PostgreSQL driver