rqlite docker image preloaded with Sakila example database
1.7K
An rqlite Docker image preloaded with the
Sakila sample database (by way of
jOOQ). One of the sakiladb image
family.
These images exist primarily as test fixtures for sq, a
command-line tool for querying SQL databases and structured data, but they are free for anyone to
use. See sq's driver guides.
rqlite is distributed SQLite, so this variant is loaded from a SQLite sakila.db baked
into the image and served over rqlite's HTTP API.
Available on Docker Hub and GitHub Container Registry.
docker run -p 4001:4001 -p 4002:4002 \
--add-host rqlite1:127.0.0.1 \
-d sakiladb/rqlite:latest
The Sakila data is baked into the image, so there is no initialization step at startup; the
container is ready in a few seconds. --add-host rqlite1:127.0.0.1 makes the baked advertise
hostname (rqlite1) resolve inside the container; without it rqlite still serves on localhost:4001
but logs a startup warning.
The image declares a Docker
HEALTHCHECK, so you can wait for
readiness rather than guessing. Its status becomes healthy once the node is ready to serve:
docker run -p 4001:4001 -p 4002:4002 --add-host rqlite1:127.0.0.1 \
-d --name sakila sakiladb/rqlite:latest
until [ "$(docker inspect -f '{{.State.Health.Status}}' sakila)" = healthy ]; do sleep 1; done
In Docker Compose, gate dependents with depends_on: { condition: service_healthy }.
When you are done, remove the container (docker rm -f sakila for the named form above, or
docker rm -f $(docker ps -q --filter ancestor=sakiladb/rqlite:latest) for the unnamed Quick-start
container).
Tip
Building or testing on GitHub Actions? Pull from GHCR (`ghcr.io/sakiladb/rqlite`). Docker Hub rate-limits pulls and CI runners share IP addresses, so the limit is reached quickly; GHCR isn't throttled the same way, especially from within GitHub's network.
| Setting | Value |
|---|---|
| host | localhost |
| HTTP port | 4001 |
| Raft port | 4002 |
| database | sakila |
| user | sakila |
| password | p_ssW0rd |
The rqlite HTTP API is reachable directly with curl:
$ curl -u sakila:p_ssW0rd \
'http://localhost:4001/db/query?level=strong&q=SELECT+first_name,last_name+FROM+actor+LIMIT+3'
{"results":[{"columns":["first_name","last_name"],"types":["TEXT","TEXT"],
"values":[["PENELOPE","GUINESS"],["NICK","WAHLBERG"],["ED","CHASE"]]}]}
With sq (install), use the
rqlite:// scheme. Because this is a single node advertising a container-internal hostname
(rqlite1), add ?disableClusterDiscovery=true so the client talks to the published port directly.
The flag is specific to this single-node-on-Docker topology, not a requirement of the driver: a real
multi-node cluster whose peer hostnames are resolvable from the client leaves discovery on (the
default) so leader redirects and failover work automatically.
$ sq add 'rqlite://sakila:p_ssW0rd@localhost:4001?disableClusterDiscovery=true' --handle @sakila_rq
@sakila_rq rqlite sakila@localhost:4001
$ sq '@sakila_rq.actor | .[0:5]'
actor_id first_name last_name last_update
1 PENELOPE GUINESS 2006-02-15T04:34:33Z
2 NICK WAHLBERG 2006-02-15T04:34:33Z
3 ED CHASE 2006-02-15T04:34:33Z
4 JENNIFER DAVIS 2006-02-15T04:34:33Z
5 JOHNNY LOLLOBRIGIDA 2006-02-15T04:34:33Z
The rqlite CLI also works. Install it natively (brew install rqlite
on macOS) and run it against the published port; it defaults to 127.0.0.1:4001, so no flags are
needed beyond the credentials:
$ rqlite --user sakila:p_ssW0rd
127.0.0.1:4001> SELECT count(*) FROM film;
+----------+
| count(*) |
+----------+
| 1000 |
+----------+
To run the CLI from the rqlite/rqlite image instead of installing it, override the entrypoint (the
image's default entrypoint is the server). On Docker Desktop or Colima (macOS), reach the published
port via host.docker.internal, not --network host, which on macOS attaches to the Docker VM
rather than your laptop (on Linux, --network host with -H localhost works):
docker run --rm -i --entrypoint rqlite rqlite/rqlite \
-H host.docker.internal -p 4001 --user sakila:p_ssW0rd
The standard Sakila sample database: 16 tables and 7 views, owned by the sakila user. It is the
same SQLite dataset the sqlite/duckdb file fixtures derive from, so
the object set, row counts, and data match the rest of the family.
sq inspect shows the whole schema (tables, views, row counts, and
columns) at a glance:
$ sq inspect @sakila_rq
SOURCE DRIVER NAME FQ NAME SIZE TABLES VIEWS LOCATION
@sakila_rq rqlite main main - 16 7 rqlite://sakila:xxxxx@localhost:4001?disableClusterDiscovery=true
NAME TYPE ROWS COLS
actor table 200 actor_id, first_name, last_name, last_update
address table 603 address_id, address, address2, district, city_id, postal_code, phone, last_update
category table 16 category_id, name, last_update
city table 600 city_id, city, country_id, last_update
country table 109 country_id, country, last_update
customer table 599 customer_id, store_id, first_name, last_name, email, address_id, active, create_date, last_update
film table 1000 film_id, title, description, release_year, language_id, original_language_id, rental_duration, rental_rate, length, replacement_cost, rating, special_features, last_update
film_actor table 5462 actor_id, film_id, last_update
film_category table 1000 film_id, category_id, last_update
film_text table 1000 film_id, title, description
inventory table 4581 inventory_id, film_id, store_id, last_update
language table 6 language_id, name, last_update
payment table 16049 payment_id, customer_id, staff_id, rental_id, amount, payment_date, last_update
rental table 16044 rental_id, rental_date, inventory_id, customer_id, return_date, staff_id, last_update
staff table 2 staff_id, first_name, last_name, address_id, picture, email, store_id, active, username, password, last_update
store table 2 store_id, manager_staff_id, address_id, last_update
actor_info view 200 actor_id, first_name, last_name, film_info
customer_list view 599 ID, name, address, zip code, phone, city, country, notes, SID
film_list view 997 FID, title, description, category, price, length, rating, actors
nicer_but_slower_film_list view 997 FID, title, description, category, price, length, rating, actors
sales_by_film_category view 16 category, total_sales
sales_by_store view 2 store, manager, total_sales
staff_list view 2 ID, name, address, zip code, phone, city, country, SID
The object set and row data match the family, but rqlite is distributed SQLite, so a few engine traits differ:
sq uses the rqlite driver. sq inspect reports DRIVER: rqlite. Reaching the single-node
image from the host needs ?disableClusterDiscovery=true, because the node advertises a
container-internal hostname (rqlite1) the host cannot resolve. That is a trait of this single-node
Docker setup, not the driver: a real multi-node cluster with host-resolvable peers leaves discovery
on (the default) for leader redirects and failover.film_text is a plain table (populated from film). SQLite full-text search needs an FTS5
virtual table, which is schema-visible and would push the count past 16, so (like the sqlite,
duckdb, and oracle variants) full-text search is omitted for parity.sales_by_film_category / sales_by_store totals format differently. SQLite sums the
DECIMAL amounts in floating point, so the totals differ in presentation from the NUMERIC-exact
engines (e.g. 4656.3 vs 4656.30). This is intrinsic to SQLite and is shared identically by the
sqlite and duckdb fixtures.sakila); there is no concept of
multiple schemas or databases on a node.address has no location column (the spatial GEOMETRY column upstream MySQL Sakila ships is
dropped across the whole family).Each rqlite major version is published as its own image tag. latest tracks the newest version
(currently 10).
| rqlite | sakiladb Release | Architecture | Docker Hub | GitHub Container Registry |
|---|---|---|---|---|
| 10 | v10.0.12 | amd64, arm64 | sakiladb/rqlite:10, :latest | ghcr.io/sakiladb/rqlite:10, :latest |
The image tag tracks the rqlite major version. sakiladb Release is the git tag the current
image was built from (see releases); the version is
v{MAJOR}.{MINOR}.{PATCH} with the major tracking rqlite (ARG RQLITE_VERSION, currently
10.2.0) and the minor/patch tracking sakiladb's own revisions (so successive v10.x.y
releases all surface as :10). Every version is published to both
Docker Hub and
GitHub Container Registry, built for
amd64 + arm64, and signed with cosign.
A cluster-compose.yml is included for testing against a real Raft cluster:
docker compose -f cluster-compose.yml up -d
This launches three nodes:
| Service | HTTP port | Role |
|---|---|---|
rqlite1 | 4001 | Leader, has Sakila |
rqlite2 | 4003 | Follower |
rqlite3 | 4005 | Follower |
Followers boot with empty volumes and receive Sakila from the leader via Raft snapshot within a few seconds. Each node's role can be polled directly on its own port:
$ for port in 4001 4003 4005; do
echo -n "port $port: "
curl -s -u sakila:p_ssW0rd "http://localhost:$port/status" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['store']['raft']['state'])"
done
port 4001: Leader
port 4003: Follower
port 4005: Follower
Every node's HTTP port is published, so you can query any node directly from your laptop. Point your client at the node's port and disable cluster discovery:
# the leader (reads + writes), on 4001
sq add 'rqlite://sakila:p_ssW0rd@localhost:4001?disableClusterDiscovery=true' --handle @rq_leader
# a follower (reads), on 4003
sq add 'rqlite://sakila:p_ssW0rd@localhost:4003?disableClusterDiscovery=true' --handle @rq_follower
Why
disableClusterDiscovery, and what this means on macOS. Left to discover the cluster, a client follows rqlite's leader-redirect to each node's advertised address (rqlite1,rqlite2, ...). Those names resolve inside the Docker network but not from your host, so discovery fails withadvertised peer "rqlite1" is not resolvable from this host. This is true on every OS: Docker Desktop and Colima on macOS don't change it, and--network hostwon't help (on macOS it attaches to the Docker VM, not your laptop). Disabling discovery makes the client talk to the published port directly, which is all you need to query the fixture.To exercise the real discovery + leader-redirect path locally, run a native cluster instead of the Docker one: rqlite's
sakila-start-rqlite-cluster.sh (brew install rqlite) starts three nodes bound to127.0.0.1, so discovery returns host-reachable addresses andsqconnects withoutdisableClusterDiscovery.
Tear down:
docker compose -f cluster-compose.yml down -v
Maintainers: releases are tag-driven. Pushing a semver tag vN.x.y builds and publishes that rqlite
major version; the version is derived from the tag, so there are no per-version branches. See
CLAUDE.md for the full, repeatable procedure.
v10.0.12): reworked the CLI and cluster guidance for Docker Desktop /
Colima (native brew install rqlite, a host.docker.internal form for the dockerized CLI, and
querying the cluster from the host with disableClusterDiscovery). The Sakila dataset and schema
are unchanged.sales_by_store no longer carries a stray leading
store_id column (it is now store, manager, total_sales), and customer_list / staff_list use
the canonical zip code alias (was zip_code). The column set is now in exact parity with the rest
of the family.last_update timestamps now match the canonical MySQL Sakila byte for byte.ghcr.io/sakiladb/rqlite) alongside Docker Hub.film_text is added as a
plain table and the aggregating views (film_list, nicer_but_slower_film_list, actor_info) use
deterministic group_concat(... ORDER BY ...) so their output matches the other variants.VOLUME,
and the build re-verifies a fresh node from the persisted dir before publishing (fixes a
previously empty published image).MIT.
Content type
Image
Digest
sha256:6d07c65a7…
Size
26 MB
Last updated
3 months ago
docker pull sakiladb/rqlite