title: 'Docker' description: 'Run Spice.ai as a Docker container.' sidebar_label: 'Docker' sidebar_position: 4 tags:
This guide describes how to run Spice.ai as a Docker container, either directly with docker run, with Docker Compose, or by building a custom image that bundles a Spicepod and data files. For Kubernetes deployments, see the Kubernetes deployment guide (opens in a new tab).
Run the latest Spice.ai image with a local Spicepod mounted into the container:
The arguments after the image name are passed to spiced. Without them, spiced listens only on 127.0.0.1 inside the container, and the published ports cannot reach it.
The examples on this page publish the ports on the host's 127.0.0.1 only. On Docker Engine versions before 28.0.0, hosts on the same local network can still reach ports published on 127.0.0.1 (opens in a new tab), so on those versions also configure API key authentication or a host firewall. To accept connections from other machines, publish them on all interfaces (for example, -p 8090:8090) and require API key authentication (opens in a new tab), because a runtime without it serves every client that can reach the port.
Spice listens on three ports:
8090 — HTTP API and /health endpoint9090 — Prometheus metrics (optional)50051 — Arrow Flight (gRPC) for high-throughput query resultsAs of Spice v2.0, AI features (embeddings, local model inference, search) are included in the default image — no separate tag is required. The data-only image, without AI/ML dependencies, is published only in nightly builds for open source and is available as a production-ready distribution through Spice Cloud and Spice.ai Enterprise (opens in a new tab).
Browse all published tags at hub.docker.com/r/spiceai/spiceai/tags (opens in a new tab).
spicepod.yaml file. See Spicepods (opens in a new tab).| Tag | Description |
|---|---|
latest | Latest stable release. Includes AI features (embeddings, local model inference, vector search) by default. |
<version> | A specific stable release, e.g. 2.0.0. Recommended for production for reproducible deployments. |
:::note
The -models image tags were removed in Spice v2.0 — AI/ML support is now part of the default image. The data-only image (without AI/ML dependencies) is published only in nightly builds for open source.
:::
Pin to a specific version in production to avoid unexpected upgrades:
docker-compose.yaml:
Start the container:
For deployments that ship a Spicepod and data with the runtime, build a custom image that copies them in:
Build and run:
:::warning Do not bake secrets into images
Image layers are cached and distributed. Use --env-file, docker run -e, or a secret manager such as Docker secrets (opens in a new tab), HashiCorp Vault (opens in a new tab), or AWS Secrets Manager (opens in a new tab) to inject credentials at runtime.
:::
The environment secret store (opens in a new tab) resolves ${secrets:<key>} from the environment variable SPICE_<key> or <key>, trying the key as written and then in uppercase. For example, ${secrets:pg_pass} reads SPICE_PG_PASS or PG_PASS.
Pass secrets at runtime with --env-file (preferred) or -e:
Common runtime variables:
| Variable | Purpose |
|---|---|
SPICED_LOG | Log level: ERROR, WARN, INFO, DEBUG, TRACE. Default INFO. |
SPICE_<NAME> | A secret referenced from a Spicepod as ${secrets:<name>}. |
TMPDIR | Temporary directory. The image sets it to /app/tmp; see Temporary files (opens in a new tab). |
For workloads that use file-based acceleration (for example, DuckDB or SQLite), mount a host directory or named volume so data survives container restarts:
In the Spicepod, configure the accelerator to write under the mount path, for example duckdb_file: /data/taxi_trips.db.
The published images are built FROM scratch and contain only the files the runtime needs — there is no /tmp. The image therefore ships TMPDIR=/app/tmp and creates that directory owned by the nobody (65534) user it runs as, so anything resolving the OS temporary directory has somewhere to write. Acceleration snapshots stage their tar archive there before uploading, and it is also the default target for query spill when runtime.query.temp_directory (opens in a new tab) is unset.
/app/tmp lives on the container's writable layer, which is usually small and is discarded when the container is removed. For workloads that snapshot large accelerations or spill large sorts and joins, give the temporary directory a volume of its own:
Setting runtime.query.temp_directory in the Spicepod covers query spill specifically; TMPDIR covers everything else that asks the operating system for a temporary path.
Spice exposes /health (process up) and /v1/ready (components ready) on the HTTP port. Use these in container orchestrators or load balancers:
The spiceai/spiceai image contains only spiced and its libraries, with no shell, curl, or wget, so a Docker or Docker Compose healthcheck that runs a command inside the container cannot work. Probe these endpoints over HTTP from outside the container instead, for example with a Kubernetes httpGet probe or a load balancer health check.