Hands-on examples for the GitHub Container Registry image ghcr.io/crosseyedcat/rustdb. Commands below match the current CLI and packaged config.toml; re-verify after upgrading images (see Verification).
This cookbook focuses on:
- Running RustDB from Docker with persistent data
- Using the CLI (
info,create,query,server) - Understanding configuration and the most useful env vars
- Common workflows (batch SQL, QUIC server, smoke scripts, benchmarks)
- Using RustDB embedded / in-process (library API) for tests and tools
For a browser-based try-it flow without Docker, see the interactive sandbox: sandbox.md (GitHub Codespaces).
CI publishes several tag styles (see .github/workflows/ci-cd.yml and docker/metadata-action):
| Tag / pattern | Purpose |
|---|---|
latest |
Default branch when enabled by metadata |
main, develop |
Branch builds |
sha-<short> |
Short Git SHA (reproducible alongside branch tags) |
pr-<n> |
Pull-request pipelines |
For bit-for-bit reproducibility, pin by digest from the package page:
export RUSTDB_IMAGE="ghcr.io/crosseyedcat/rustdb:main"
docker pull "$RUSTDB_IMAGE"
# Optional: export RUSTDB_IMAGE="ghcr.io/crosseyedcat/rustdb@sha256:<digest>"Note: the binary in the image may lag behind main in Git. Always check rustdb server --help and /app/config/config.toml inside the container. For QUIC framing, TLS leaf export, and clients, see docs/network/README.md.
docker run --rm "$RUSTDB_IMAGE" rustdb --versionExpected: rustdb 0.1.0 (or the version in the image’s Cargo.toml).
docker run --rm "$RUSTDB_IMAGE" rustdb infoPrints version, default language, OS, and architecture inside the container (typically linux / x86_64 or aarch64).
docker run --rm "$RUSTDB_IMAGE" rustdb language list
docker run --rm "$RUSTDB_IMAGE" rustdb language show
docker run --rm "$RUSTDB_IMAGE" rustdb language set enrustdb query runs SQL locally through SqlEngine (same parse → plan → execute path as the QUIC server), using the configured data directory.
docker run --rm "$RUSTDB_IMAGE" rustdb query "SELECT 1"
docker run --rm "$RUSTDB_IMAGE" rustdb query "SELECT 1" -d mydbThe second form uses -d / --database to resolve data under data_directory from config (default ./data, i.e. /app/data when using the image layout).
Inspect the planner/optimizer tree without changing the wire protocol:
docker run --rm "$RUSTDB_IMAGE" rustdb query "EXPLAIN SELECT 1"
docker run --rm "$RUSTDB_IMAGE" rustdb query "EXPLAIN ANALYZE INSERT INTO t (a) VALUES (1)"See docs/sql-explain.md for syntax, supported statements, and DML caveats.
Use --batch-file to run one statement per line in a single process, using one SessionContext.
This is required if you want to test transactions (BEGIN/COMMIT/ROLLBACK) across multiple statements.
Auto-commit note: if you run DML outside an explicit BEGIN … COMMIT, RustDB executes each DML
statement as an implicit short transaction (auto-commit). That means standalone
INSERT/UPDATE/DELETE statements are WAL-logged and committed at statement end (subject to the
selected durability mode; see docs/durability-and-recovery.md).
Example via stdin (--batch-file -):
docker run --rm -i \
-v rustdb-data:/app/data \
"$RUSTDB_IMAGE" \
sh -c 'rustdb --config /app/config/config.toml query --batch-file -' <<'SQL'
BEGIN TRANSACTION
INSERT INTO demo_t (a) VALUES (1)
ROLLBACK
SQLCoverage of SQL features is still growing; see README.md for project status and test limitations.
For tests, local tooling, or embedding RustDB inside another Rust process, you can use SqlEngine
directly (no QUIC server). This is the same execution pipeline used by rustdb query.
use rustdb::network::engine::{EngineHandle, SessionContext};
use rustdb::network::sql_engine::SqlEngine;
let data_dir = std::path::PathBuf::from("./data/embedded-demo");
let engine = SqlEngine::open(data_dir).unwrap();
let mut ctx = SessionContext::default();
engine.execute_sql("CREATE TABLE t (a INTEGER)", &mut ctx).unwrap();
engine.execute_sql("INSERT INTO t (a) VALUES (1)", &mut ctx).unwrap();
let out = engine.execute_sql("SELECT a FROM t", &mut ctx).unwrap();
println!("{out:?}");To simulate a process crash in tests, close the engine (drop it) and reopen it on the same data
directory. With WAL enabled (default), the invariants in docs/durability-and-recovery.md
should hold after open().
use rustdb::network::engine::{EngineHandle, SessionContext};
use rustdb::network::sql_engine::SqlEngine;
let dir = tempfile::TempDir::new().unwrap();
let data_dir = dir.path().to_path_buf();
// Setup schema.
{
let engine = SqlEngine::open(data_dir.clone()).unwrap();
let mut ctx = SessionContext::default();
engine.execute_sql("CREATE TABLE t (a INTEGER)", &mut ctx).unwrap();
}
// Simulate: BEGIN; INSERT; <crash>
{
let engine = SqlEngine::open(data_dir.clone()).unwrap();
let mut ctx = SessionContext::default();
engine.execute_sql("BEGIN TRANSACTION", &mut ctx).unwrap();
engine.execute_sql("INSERT INTO t (a) VALUES (1)", &mut ctx).unwrap();
drop(ctx); // no COMMIT/ROLLBACK
}
// Reopen: WAL replay should undo the uncommitted insert.
{
let engine = SqlEngine::open(data_dir.clone()).unwrap();
let mut ctx = SessionContext::default();
let out = engine.execute_sql("SELECT a FROM t", &mut ctx).unwrap();
println!("{out:?}");
}This repository also contains a small standalone binary, rustdb_tool, intended for quick health
checks and WAL diagnostics for a data directory:
cargo run --bin rustdb_tool -- health --data-dir ./data/mydb
cargo run --bin rustdb_tool -- wal-status --data-dir ./data/mydb
cargo run --bin rustdb_tool -- checkpoint --data-dir ./data/mydbrustdb create creates a directory for a named database and writes a small .rustdb marker file. It does not register a full catalog entry everywhere in the stack—treat it as a filesystem helper.
docker run --rm "$RUSTDB_IMAGE" rustdb create demo --data-dir /app/dataEphemeral containers lose /app/data unless you mount a volume (next sections).
The network entrypoint is QUIC over UDP with ALPN rustdb-v1. Map ports with /udp.
The image ships config.toml at /app/config/config.toml with network.port = 5432. Recommended invocation:
docker rm -f rustdb-server 2>/dev/null || true
docker run -d --name rustdb-server \
-p 15432:5432/udp \
-v rustdb-data:/app/data \
"$RUSTDB_IMAGE" \
rustdb --config /app/config/config.toml server --host 0.0.0.0 --cert-out /tmp/server.der--host 0.0.0.0is required for connections from the host or other containers.--cert-outwrites the dev TLS leaf (DER) forrustdb_quic_client --cert(copy out withdocker cpif needed).
Stop:
docker stop rustdb-server && docker rm rustdb-serverDockerfile still EXPOSEs 8080/8081 for historical layout; the QUIC listener port comes from config or --port. To use another port: --port 8080 and -p 18080:8080/udp.
Example: named volume for data and a read-only host config (paths follow the Dockerfile):
docker run --rm \
-v rustdb-data:/app/data \
-v "$(pwd)/config.toml:/app/config/config.toml:ro" \
"$RUSTDB_IMAGE" \
rustdb --config /app/config/config.toml infoThe container expects a config file like /app/config/config.toml (see repository config.toml).
The most used keys in the current image:
data_directory: base directory for database storage (in the image:/app/data)language: interface language (e.g.en)network.host/network.port: QUIC/UDP listener bind address and port
RustDB reads a small set of env vars used in different parts of the stack:
RUST_LOG: logging filter fortracing-subscriber(server)RUSTDB_TRACE_CHROME_PATH: when set, enablestracing-chromeJSON trace output (server)RUSTDB_NAME,RUSTDB_DATA_DIR,RUSTDB_MAX_CONNECTIONS,RUSTDB_LANGUAGE: config overrides used byDatabaseConfig::from_env()(CLI / config helpers)
Example:
docker run --rm \
-e RUST_LOG=info \
-e RUSTDB_TRACE_CHROME_PATH=/app/logs/trace.json \
-v rustdb-data:/app/data \
"$RUSTDB_IMAGE" \
rustdb --config /app/config/config.toml infoThe GHCR image contains only the rustdb binary. Build rustdb_quic_client (and optionally rustdb_load) from source:
git clone https://github.com/CrossEyedCat/RustDB.git && cd RustDB
cargo build --release --bin rustdb_quic_clientThen follow docs/network/README.md: run rustdb server, pass --cert / --server-name, and use --addr for host:port.
The repository script re-runs the main checks against an image (default ghcr.io/crosseyedcat/rustdb:main):
./scripts/verify-cookbook-docker.sh
# or: RUSTDB_IMAGE=ghcr.io/crosseyedcat/rustdb:sha-abc1234 ./scripts/verify-cookbook-docker.shscripts/bench_via_ghcr_image.sh pulls the image, uses a data volume, warms up bench_t, starts rustdb server with --cert-out, copies the leaf cert to the host, and runs scripts/bench_sqlite_vs_rustdb.py.
export RUSTDB_IMAGE="ghcr.io/crosseyedcat/rustdb:main"
./scripts/bench_via_ghcr_image.shBy default this script runs the server on UDP port 8080 inside the container (UDP_PORT on the host maps to 8080/udp). That differs from the packaged /app/config/config.toml default (5432) but matches the script’s expectations; set UDP_PORT if you need a different host port.
On Windows with Docker Desktop, you can use the PowerShell helper:
$env:RUSTDB_IMAGE = "ghcr.io/crosseyedcat/rustdb:main"
.\scripts\bench_via_ghcr_image.ps1Or Git Bash: "C:\Program Files\Git\bin\bash.exe" -lc './scripts/bench_via_ghcr_image.sh'.
Optional: set POSTGRES_DSN for Postgres rows in the report. Output defaults under target/bench_docker_ghcr/ (or OUT_DIR if set).
The Dockerfile defines a profiler stage (Linux perf + cargo flamegraph). Example:
docker build -t rustdb-prof --target profiler .
# See comments in Dockerfile for run invocationFor CI-style flame graphs and tracing, see CONTRIBUTING.md (workflow_dispatch jobs).
docker-compose.yml is an illustrative stack (Redis, Prometheus, Grafana, etc.). Comments mentioning HTTP/gRPC ports do not match the current QUIC/UDP server. For a minimal RustDB setup, prefer the docker run examples above and override the service command to rustdb --config /app/config/config.toml server ... with UDP port mappings if you adapt Compose.
- sandbox.md — try RustDB in GitHub Codespaces (CLI, ephemeral seed data)
- README.md — goals, status, and test limitations
- Network (QUIC) — protocol and client/server boundary
- Dockerfile,
docker-compose.yml— build and optional orchestration - CONTRIBUTING.md — CI jobs and contribution workflow
Run --help inside the container to confirm flags for the image you pinned:
docker run --rm "$RUSTDB_IMAGE" rustdb --help
docker run --rm "$RUSTDB_IMAGE" rustdb query --help
docker run --rm "$RUSTDB_IMAGE" rustdb server --helpCommon commands:
rustdb info: prints system inforustdb create <name>: creates a database directory (filesystem helper)rustdb query <SQL>: runs one statementrustdb query --batch-file <path|->: runs one statement per line (transactions span lines)rustdb server: starts the QUIC/UDP server