Skip to content

Runners

Container runners are optional features that allow steps to execute inside Docker containers or Kubernetes pods instead of directly on the worker host.

RunnerHow it works
local (default)Step runs directly on the worker host
dockerStep runs in a Docker container with workspace at /workspace
podStep runs as a Kubernetes pod with workspace via init container
  1. Build the worker with the docker feature:
    Terminal window
    cargo build -p stroem-worker --features docker
  2. Add docker: {} to the worker config
  3. The worker needs Docker daemon access (local socket, or DinD sidecar in K8s)
tags:
- script
- docker
docker: {}
runner_image: "ghcr.io/fremvaerk/stroem-runner:latest"
  1. Build the worker with the kubernetes feature:
    Terminal window
    cargo build -p stroem-worker --features kubernetes
  2. Add a kubernetes: section to the worker config
  3. The worker needs in-cluster credentials or a kubeconfig with permissions to create/get/delete pods
  4. The server must be reachable from inside the pod (the init container downloads workspace tarballs)
tags:
- script
- kubernetes
kubernetes:
namespace: stroem-jobs
init_image: curlimages/curl:latest # optional, default

Both features can be enabled simultaneously:

server_url: "http://stroem-server:8080"
worker_token: "your-token"
worker_name: "worker-1"
max_concurrent: 4
poll_interval_secs: 2
workspace_cache_dir: /var/stroem/workspace-cache
tags:
- script
- docker
- kubernetes
runner_image: "ghcr.io/fremvaerk/stroem-runner:latest"
docker: {}
kubernetes:
namespace: stroem-jobs

Tags control which steps a worker can claim. Each step automatically computes required_tags based on its action type and runner configuration:

ActionRunnerRequired tags
scriptlocal (default)["script"]
scriptdocker["docker"]
scriptpod["kubernetes"]
docker["docker"]
pod["kubernetes"]
task[] (server-dispatched)

A worker claims a step only when all of the step’s required_tags are present in the worker’s tags list. This ensures specialized workloads route to capable workers.

Worker configuration:

tags:
- script # can run local scripts
- docker # can run docker steps
- kubernetes # can run pod steps
- gpu # custom tag for GPU-enabled work

Step with custom tags:

flow:
train-model:
action: train-gpu
tags: ["gpu"] # adds to required_tags

A step with type: script, runner: docker, tags: ["gpu"] requires ["docker", "gpu"] — only workers with both tags can claim it.

If no active worker has all required tags for a step, the step remains ready but unclaimed. After unmatched_step_timeout_secs (default 30 seconds, configurable in server recovery settings), the step fails with error: "No active worker with required tags to run this step".

Example scenario: A step requires ["kubernetes"] but all workers have ["script", "docker"]. After 30 seconds, the step fails. To fix: add a worker with Kubernetes runner enabled, or remove the runner: pod requirement.

The official runner image (ghcr.io/fremvaerk/stroem-runner) and worker image ship with these tools pre-installed:

ToolDescription
bashDefault shell
curlHTTP client
gitVersion control
jqJSON processor
yqYAML/JSON/XML processor
tar / gzipArchive and compression
unzipZIP extraction
sshOpenSSH client
ToolDescription
sopsMozilla SOPS — encrypted file editing
valsHelmfile vals — multi-backend secret resolution
ToolDescription
uvPython package manager and runner
bunJavaScript/TypeScript runtime

Example — Python with dependencies:

actions:
analyze:
type: script
runner: docker
script: |
uv pip install pandas requests --system
uv run python /workspace/scripts/analyze.py

Example — TypeScript:

actions:
generate-report:
type: script
runner: docker
script: |
cd /workspace
bun install
bun run scripts/report.ts

When deploying via Helm, use these values to configure runners:

Terminal window
# Enable Kubernetes runner
helm install stroem ./helm/stroem \
--set worker.kubernetes.enabled=true \
--set worker.kubernetes.namespace=stroem-jobs
# Enable Docker runner via DinD sidecar
helm install stroem ./helm/stroem \
--set worker.dind.enabled=true

See Helm / Kubernetes for full deployment details.