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.
Prerequisites
Section titled “Prerequisites”- Docker Desktop or Docker Engine installed and running
- The base image available locally or from a registry
Configuration
Section titled “Configuration”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": {} }}| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable container isolation |
image | string | ghcr.io/elanamir/cliq-runner:latest | Docker image to use |
memory | string | "4g" | Container memory limit |
cpus | string | "2" | CPU limit |
network_mode | string | "bridge" | Docker network mode (bridge, none) |
read_only_rootfs | boolean | true | Mount root filesystem as read-only |
max_containers | number | 4 | Maximum concurrent containers |
extra_hosts | string[] | [] | Additional /etc/hosts entries |
env | object | {} | Extra environment variables |
CLI Usage
Section titled “CLI Usage”# 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 --dashboardWhen 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.
Terminal Streaming
Section titled “Terminal Streaming”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.
Custom Images
Section titled “Custom Images”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 rootRUN apt-get update && apt-get install -y postgresql-client python3-pip \ && pip3 install pandas sqlalchemy \ && rm -rf /var/lib/apt/lists/*USER nodeImage Resolution Order
Section titled “Image Resolution Order”docker.imageinteam.yml(team author’s choice — rarely used)docker.imageinsettings.json(user/org default)ghcr.io/elanamir/cliq-runner:latest(base fallback)
Images are auto-pulled if not available locally.
Security Model
Section titled “Security Model”| Layer | Protection |
|---|---|
| Non-root user | Container runs as node (UID 1000) |
| Read-only rootfs | Only the workspace and /tmp are writable |
| No privilege escalation | --security-opt no-new-privileges |
| Resource limits | Memory and CPU capped per container |
| Concurrent cap | max_containers prevents resource exhaustion |
| No Docker socket | Container cannot control Docker |
| Network isolation | Configurable: bridge (default) or none (air-gapped) |
| Settings read-only | ~/.cliqrc mounted read-only |
| Tool control | Only tools baked into the image are available |
Base Image Contents
Section titled “Base Image Contents”The base image (ghcr.io/elanamir/cliq-runner) includes:
| Tool | Purpose |
|---|---|
| Node.js 22 | Cliq runtime |
| git | Version control |
| curl | HTTP requests, API calls |
| tmux | Agent session management |
Cursor CLI (agent) | Default AI agent |
| cliq | Pipeline orchestration |
Doctor Checks
Section titled “Doctor Checks”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)
A2A Integration
Section titled “A2A Integration”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.
Troubleshooting
Section titled “Troubleshooting”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.
HUG Server
Section titled “HUG Server”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.
Production Deployment
Section titled “Production Deployment”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.