π₯ Meerschaum Stack¶
The Stack uses Docker Compose to run a database, the API and console, Valkey, and Grafana together. Start it with mrsm stack up -d. See upgrades and backups when maintaining an existing Stack.
π³ Services¶
The default stack starts 4 services:
| Service | Description | Image |
|---|---|---|
| db | TimescaleDB instance corresponding to sql:main. |
timescale/timescaledb-ha:pg18 |
| api | Production Meerschaum Web API server corresponding to api:main. |
bmeares/meerschaum:<version>-full |
| valkey | Valkey instance corresponding to valkey:main. Used for caching sessions in by api. |
valkey/valkey-bundle:latest |
| grafana | Grafana instance connected to sql:main. |
grafana/grafana:latest |
You can edit the stack's Docker Compose file with mrsm edit config stack.
The api service runs the full image of the same release as the mrsm that writes the compose file (bmeares/meerschaum:<version>-full), so the API server and the client use the same version, and API plugins and the Dash console work without further installs. The image is built for linux/amd64 and linux/arm64.
Upgrading an existing stack to 5.x
Earlier versions of the stack ran bmeares/meerschaum:api. mrsm stack regenerates the compose file on every run: a root without config/stack.yaml takes the new image the next time you run mrsm stack up -d, which recreates only the api container (the volumes and the database are kept). After pip install --upgrade meerschaum the tag follows the new version in the same way, so run mrsm stack up -d after every upgrade (or mrsm stack pull first to fetch the image ahead of time).
A config/stack.yaml that has a docker-compose.yaml section keeps its own api image, because the defaults only fill in what is missing. To move it, edit services:api:image with mrsm edit config stack to bmeares/meerschaum:<version>-full (or delete the api service's image line so the default applies), then run mrsm stack up -d. mrsm stack config prints the compose file that will run.
Entering the Meerschaum Docker image
Hop into a shell in the api service:
ποΈ The Database Setup¶
First-run setup, extensions, and health checks
The first time the db service starts on an empty volume, the image's entrypoint sets up the database. A new stack mounts Meerschaum's setup script as a single file into the image's own setup directory:
volumes:
- meerschaum_db_data:/home/postgres/pgdata
- <root>/db/initdb/create-extensions.sql:/docker-entrypoint-initdb.d/100_meerschaum.sql:z,ro
so the image's scripts run first and Meerschaum's runs last:
- The image creates the
timescaledbextension in thepostgres,template1andPOSTGRES_DBdatabases (new databases created fromtemplate1have it too). TIMESCALEDB_TELEMETRY: 'off'(the stack default) turns off TimescaleDB's telemetry.timescaledb-tunetunespostgresql.conffor the container's memory and CPU limits. SetNO_TS_TUNE: 'true'in the service'senvironmentto skip it (the stack'scommandstill setsmax_connectionsandshared_buffers, which win over the tuned values).- The image creates the
timescaledb_toolkitextension. create-extensions.sqlcreatestimescaledb,postgis,timescaledb_toolkitandpg_stat_statementsinPOSTGRES_DB, each only when the image provides it (aNOTICEin the container's log names each one it skips, so another PostgreSQL image such aspostgres:18orpostgis/postgisstill starts), and addspg_stat_statementstoshared_preload_libraries(keeping the entries already there) so its view can be queried once the server is up.
The db healthcheck asks the server over TCP (pg_isready -h 127.0.0.1 -p 5432 ..., with a 300 second start_period): the entrypoint's setup server only listens on its Unix socket, so the service turns healthy (and api and grafana start) only after the setup is done. A passing check turns it healthy at once; the long start period only keeps a slow first setup (e.g. on a Raspberry Pi) from being reported unhealthy, which would abort mrsm stack up.
The setup runs once
Docker runs the setup only when the data volume is empty. mrsm stack writes create-extensions.sql under your root directory once, when it is missing, and never overwrites it, so you may edit it before the first mrsm stack up (e.g. to create more extensions). Changing it later does nothing for an existing database: see Upgrading the stack (mrsm upgrade extensions) for updating the extensions and settings of a database that already exists.
Stacks created before 5.0
Earlier versions mounted the whole <root>/db/initdb directory over /docker-entrypoint-initdb.d, which hid the image's own scripts (no telemetry opt-out, no tuning, no extensions in template1), and checked health over the Unix socket. mrsm stack regenerates the compose file on every run: a root without config/stack.yaml (v4's mrsm stack never writes one) takes the new defaults, and the next mrsm stack up -d recreates the db container once (the data volume is kept; extra scripts in <root>/db/initdb/ are no longer mounted for a future fresh volume). A stack.yaml with a docker-compose.yaml section keeps that section as it is. See the migration guide.
Docker Images¶
Choose a variant of bmeares/meerschaum:
| Tag | Included | Best suited to |
|---|---|---|
full / latest |
Native CLI, Python SDK and all extras (including Dash/API), Cargo, rustc, C/C++ build tools, pip, Git and interactive tools | First-time users and plugin development |
rust |
Native CLI, core API/MCP, database connectors and runtime libraries; no Python or compilers | Small native deployments and prebuilt Rust plugins |
rust-full |
Everything in rust, plus Cargo, rustc, Git and native build tools; no Python |
Building Rust source plugins without a Python installation |
slim / minimal |
Python and the base wheel; no optional extras or Rust toolchain | Small Python installations where dependencies are supplied separately |
api |
Deprecated alias of full |
Existing deployments |
Every variant runs the same Rust engine and uses the same configuration and plugin formats.
The Dash console and Python plugins require a Python variant. A .rs source plugin needs
Cargo for its first build and after edits; use rust-full or full, or ship a prebuilt plugin
with rust. The toolchain variants also cache the base dependencies for single-file Rust plugins,
so a minimal Rust plugin can build offline. Additional plugin dependencies use normal Cargo
downloads. Native-only deployments never need a Python host. Mount /home/meerschaum/.cargo
when you want dependency downloads to persist across rust-full or full containers.
Pin a version with {version}-{variant}, for example 5.0.2-rust or
5.0.2-full. Releases publish linux/amd64 and linux/arm64 and update the floating tags;
pre-releases publish only version-qualified tags, for linux/amd64.
{version}-api continues to alias {version}-full.
Build locally with docker buildx build --target rust --load -t mrsm:rust . (replace
rust with rust-full, slim, or full). A plain docker build . produces full.
full intentionally has a larger size budget because it includes both language toolchains.
Native drivers may still require vendor libraries, such as Oracle Instant Client.
Containers are upgraded by pulling the desired image and recreating the service, preserving
the mounted Meerschaum root. mrsm upgrade mrsm inside a container reports this ownership
rather than changing packages in the running image.
ποΈ Requirements¶
You need Docker installed to run the stack. To install Docker, follow this guide or do the following:
Install Docker Desktop.
π’ Starting the Stack¶
Run the following command to bring up a database and Grafana:
The stack command is a wrapper around a pre-configured docker-compose project. Don't worry if you don't have docker-compose installed; in case it's missing, Meerschaum will automatically install it within a virtual environment for its own use.
Refer to the docker-compose overview page to see the available stack commands.

Grafana is included in the Meerschaum stack, pre-configured with the Meerschaum TimescaleDB database.
Open a web browser and navigate to http://localhost:3000 where you can log into Grafana with username admin, password admin.
Built-in dashboards¶
The Stack provisions two dashboards in Grafana's Meerschaum Dashboards folder. Both read the instance's internal mrsm_engine_* tables and filter by Pipe and Pipeline.
- Syncs: every completed sync.
- Overview: totals, outcomes, duration and P95, write rate (rows affected/s), failure rate, retries and chunks, the slowest Pipes and recent failures.
- Pipes: duration, write rate, failures and rows affected per Pipe, a Pipe summary and the sync history.
- Pipelines: duration, rows affected, retries and failures per Pipeline, a Pipeline summary and recorded run durations.
- Engine: what the Syncing Engine records.
- Runs: runs by outcome, run duration, node outcomes and planned actions, failures and retries, node start delay against the plan, and the recent runs.
- Freshness: each Pipe's latest sync and time since its last success, data watermarks, and each child's lag behind its parents.
- Dirty-range backlog: the parents' changed ranges each child has not synced yet, and how long they have waited.
- Nodes and Streams: failed and retried nodes, per-Pipe timing and critical-path share, and stream flushes.
Rows affected count inserted, updated, upserted and deleted rows. Replacements count deleted plus new rows; unchanged syncs affect zero rows.
Upgrading from 5.0.0rc34 or earlier
The Meerschaum Performance, Pipe Performance and Pipeline Performance dashboards are replaced by Syncs. The next mrsm stack command removes their files when they are exactly as Meerschaum wrote them, and Grafana drops them. A customized copy, a symlink or another dashboard under the same file name is kept, with a warning; delete it when you no longer need it.
Grafana queries the configured database directly with its data-source credentials. Its visibility follows those database permissions. The web console and HTTP API apply their Pipe and team access rules. See Sync metrics for capture and history limits.
πΎ Backing Up and Upgrading the Database¶
mrsm backup postgres takes an online backup of the stack's database (nothing is stopped) into
<root>/backups/postgres/<timestamp>/, and mrsm restore postgres puts a backup into a new volume
and switches the stack to it, keeping the current one. mrsm upgrade postgres moves the database
to a newer PostgreSQL major the same way (a backup first, then a verified restore). See
Backing up and restoring and
Upgrading PostgreSQL.
π Stopping the Stack¶
If you want to stop all the services in the stack, run the stack command with down:
To remove all services in the stack and delete all data, use the -v flag:
Data Loss Warning
The -v flag in stack down -v will delete ALL volumes in the stack. That includes pipes' data!
To delete a specific service's volume, run the command docker volume rm, e.g. to delete just Grafana's data:
π Editing the Stack¶
Certain parameters like the main database username and password are linked from the connectors configuration, which may be accessed with mrsm edit config.
You can find the complete Docker Compose YAML file with: