Skip to content

Docker

VectorStep and the Gateway publish multi-arch (linux/amd64 + linux/arm64) images to GHCR on every tagged release, plus an edge tag tracking the default branch. See Versions and releases for what each tag means and the VectorStep/Gateway compatibility rule:

Terminal window
docker pull ghcr.io/bantex01/vectorstep:latest
docker pull ghcr.io/bantex01/vectorstep-gateway:latest

Every published image is signed and has an SBOM attached to its GitHub release — see Verifying a release for the cosign verify command. Pin production deployments to a released semver tag (e.g. :0.1.0) rather than :latest or :edge — see Versions and releases.

This page covers pulling and running the images directly — docker run or your own docker compose file. If you just want VectorStep running with no manual wiring, use the installer instead; it manages the compose file, config, and volumes below for you.

Images contain code and committed samples only — config is never baked in. Mount a config file and point CONFIG_PATH (VectorStep) / VECTORSTEP_GATEWAY_CONFIG (Gateway) at it; secrets arrive as environment variables consumed by the config’s ${VAR} substitution. Everything writable lives under a single /data volume, so the container variant of config.yaml looks like this:

database: {url: "sqlite+aiosqlite:////data/db/runs.db"} # four slashes = absolute path
pipeline_config_dir: /data/pipelines # or a ConfigMap mount — see Kubernetes
step_library_dir: /data/steps
artifacts: {dir: /data/artifacts}
logging: {dir: /data/logs}
auth:
tokens:
- name: admin
token: ${VECTORSTEP_ADMIN_TOKEN}
role: admin
- name: webhook
token: ${VECTORSTEP_WEBHOOK_TOKEN}
role: webhook

auth.tokens isn’t optional — VectorStep refuses to start without it (or auth.allow_unauthenticated: true, only for a trusted local machine): pipeline write access is equivalent to shell access on the host it’s running on. See Securing a deployment for what each role can do.

Terminal window
export VECTORSTEP_ADMIN_TOKEN=$(openssl rand -hex 24)
export VECTORSTEP_WEBHOOK_TOKEN=$(openssl rand -hex 24)
echo "Admin token (save this — it's what you log into the UI with): $VECTORSTEP_ADMIN_TOKEN"
docker run -d \
-p 8000:8000 \
-e VECTORSTEP_ADMIN_TOKEN \
-e VECTORSTEP_WEBHOOK_TOKEN \
-v ./config.yaml:/etc/vectorstep/config.yaml:ro \
-v vectorstep-data:/data \
ghcr.io/bantex01/vectorstep:latest

The Gateway’s container config additionally needs identity.path and agents_dir pointed at /data — its default, /data/identity, already assumes that layout; only override it if you’re mounting something other than a single /data volume. See Configuration for the full field reference.

Evaluating the pair locally (docker compose)

Section titled “Evaluating the pair locally (docker compose)”

The installer manages a docker-compose.yaml for you — fetched from the public VectorStep-Dist repo into ~/.vectorstep/, refreshed on every re-run — bringing up both services from the published images with docker compose up, no build: step and no source checkout involved. It’s an evaluation/dev path, not a production one — for a real deployment, see Kubernetes.

If you’d rather write your own compose file instead of using the installer’s, VectorStep-Dist/docker-compose.yaml is worth reading first — it has the config-mounting and named-volume conventions this page describes already wired up correctly.

The installer’s compose stack binds loopback by default:

ports: ["${VECTORSTEP_BIND:-127.0.0.1}:${VECTORSTEP_PORT:-8000}:8000"]

So a fresh install never exposes an unauthenticated-by-default service to the rest of the local network. Set VECTORSTEP_BIND=0.0.0.0 in ~/.vectorstep/.env only when this host needs to serve other machines, and only once you’ve put TLS in front of it — either server.tls in config/vectorstep.yaml (see Deployment → TLS) or a terminating reverse proxy.

The Gateway publishes no host port at all — VectorStep reaches it on the compose network at ws://gateway:18780, which is all the default stack needs. If you’re pointing a Gateway MCP client, or anything else running on the host rather than in a container, at localhost:18780, add a persistent mapping to docker-compose.yaml’s gateway service:

gateway:
ports: ["127.0.0.1:18780:18780"]

then docker compose up -d to apply it — docker compose port only prints a binding that already exists, so with no ports: entry there’s nothing for it to report.

Keep it off a non-loopback interface unless it’s behind TLS and a firewall — the Gateway’s admin token can rewrite agent definitions.

  • Kubernetes — the production path once evaluation is done.
  • Deployment — the full config.yaml reference and database/migration mechanics, regardless of how you’re running the images.