Skip to content

Docker Container Isolation

Cliq can run pipelines inside Docker containers for enhanced security and reproducibility. When Docker mode is enabled, each pipeline execution runs in an isolated container with controlled resources, a read-only root filesystem, and no privilege escalation.

  • Docker Desktop or Docker Engine installed and running
  • The base image available locally or from a registry

Add a docker block to your ~/.cliqrc/settings.json:

{
"docker": {
"enabled": true,
"image": "ghcr.io/elanamir/cliq-runner:latest",
"memory": "4g",
"cpus": "2",
"network_mode": "bridge",
"read_only_rootfs": true,
"max_containers": 4,
"extra_hosts": [],
"env": {}
}
}
FieldTypeDefaultDescription
enabledbooleanfalseEnable container isolation
imagestringghcr.io/elanamir/cliq-runner:latestDocker image to use
memorystring"4g"Container memory limit
cpusstring"2"CPU limit
network_modestring"bridge"Docker network mode (bridge, none)
read_only_rootfsbooleantrueMount root filesystem as read-only
max_containersnumber4Maximum concurrent containers
extra_hostsstring[][]Additional /etc/hosts entries
envobject{}Extra environment variables
Terminal window
# Force Docker mode (overrides docker.enabled setting)
cliq run --docker
# Force local executor (overrides docker.enabled and kubernetes.enabled)
cliq run --no-docker
# Docker with dashboard only (requires running server)
cliq run --docker --dashboard

When docker.enabled is true in settings, Docker is the default for cliq run unless --no-docker is passed. The --no-docker flag forces the local executor, bypassing both Docker and Kubernetes — even when kubernetes.enabled is true. This is how pipeline Job pods run internally: cliq run --headless --force --no-docker.

By default, cliq run --docker streams pipeline output to the terminal — orchestrator logs, phase output, and command results. No server is required.

With --dashboard, terminal streaming is suppressed and a running cliq server is required. Monitor progress via the dashboard.

Override the Docker image for all pipelines by setting docker.image in settings.json:

{
"docker": {
"enabled": true,
"image": "myorg/cliq-data:1.2"
}
}

Custom images should extend the base image:

FROM ghcr.io/elanamir/cliq-runner:latest
USER root
RUN apt-get update && apt-get install -y postgresql-client python3-pip \
&& pip3 install pandas sqlalchemy \
&& rm -rf /var/lib/apt/lists/*
USER node
  1. docker.image in team.yml (team author’s choice — rarely used)
  2. docker.image in settings.json (user/org default)
  3. ghcr.io/elanamir/cliq-runner:latest (base fallback)

Images are auto-pulled if not available locally.

LayerProtection
Non-root userContainer runs as node (UID 1000)
Read-only rootfsOnly the workspace and /tmp are writable
No privilege escalation--security-opt no-new-privileges
Resource limitsMemory and CPU capped per container
Concurrent capmax_containers prevents resource exhaustion
No Docker socketContainer cannot control Docker
Network isolationConfigurable: bridge (default) or none (air-gapped)
Settings read-only~/.cliqrc mounted read-only
Tool controlOnly tools baked into the image are available

The base image (ghcr.io/elanamir/cliq-runner) includes:

ToolPurpose
Node.js 22Cliq runtime
gitVersion control
curlHTTP requests, API calls
tmuxAgent session management
Cursor CLI (agent)Default AI agent
cliqPipeline orchestration

When docker.enabled is true, cliq doctor automatically checks:

  • Docker CLI is installed
  • Docker daemon is running
  • Base image is available locally (optional — will auto-pull)
  • Image age (warns if > 30 days old)

When Docker mode is enabled and the cliq server receives A2A tasks, each task runs in its own container. The workspace is bind-mounted so polling (phases, events, verdicts) works unchanged. Containers are tracked in the SQLite database for crash recovery — orphaned containers are cleaned up on server restart.

Container limit reached: Increase docker.max_containers or wait for running tasks to complete.

Image pull fails: Check your network connection and registry authentication. For GHCR private images, run docker login ghcr.io.

Pipeline hangs in container: Check docker logs cliq-<instance-id> for container-level errors.

Air-gapped mode: Set network_mode: "none" to completely disable network access. Note that integrations requiring external API calls (Jira, GitHub) will not work.

Docker isolation applies to cliq pipeline execution. If your teams use human gates, the HUG server is deployed separately — it has its own lightweight Docker image (ghcr.io/elanamir/hug-server:latest) with only Express, PostgreSQL, and WebSocket dependencies. See HUG Server for deployment instructions.

Docker is one of three execution backends (local, Docker, Kubernetes). For running the cliq server in a Docker container on a single host, see the Production Deployment guide. For horizontally scaled deployments with K8s Job scheduling, see Kubernetes Deployment.