Docker / GHCR
If your deployment target is "wherever docker run works," installing a package manager, a Go toolchain, or a language SDK just to get one static binary onto the box is friction you shouldn't pay.
A bare VM, a CI runner, a Nomad job, a Compose stack, a pod that isn't ready for an operator — ghcr.io/whisper-sec/whisper is the same whisper CLI with nothing to install, a locked digest to pin, and three run-modes (plain CLI, MCP server, egress sidecar) behind one entrypoint.
Container images solve a narrower problem than package managers, but they solve it better for the case that actually dominates agent infrastructure: you don't control the host. A GitHub Action runner, a serverless container platform, a customer's Kubernetes cluster, an air-gapped CI pipeline — none of these let you apt install or brew install anything, but all of them can pull an OCI image. Whisper ships one multi-arch image that carries the exact same Go binary as every other channel — no separate codebase, no "the Docker build lagged the release," because the image is the release: the same CI job that cuts a CLI version bakes it into the container and pushes both in the same run.
What's in the image
ghcr.io/whisper-sec/whisper:<version> # e.g. :0.128.0
ghcr.io/whisper-sec/whisper:latest # tracks the newest tagged release
- Multi-arch manifest —
linux/amd64andlinux/arm64under one tag; Docker/containerd pick the right layer for the host automatically, so the samedocker runworks on a Graviton instance, an Apple Silicon dev box (via Docker Desktop's VM), or a plain x86 CI runner. - Entrypoint is
whisperitself — the image is not a general-purpose Linux base with the binary dropped in;ENTRYPOINT ["whisper"]means everydocker run … <args>maps straight ontowhisper <args>, so the CLI's own--helpis the image's--help. - No package manager inside — a minimal static base, so there's no
apt/apksurface to patch or scan for CVEs beyond the Go binary itself. Nothing to update but the tag. - Anonymous pull — the
whisper-secorg packages are public; nodocker loginneeded to read.
Verify the image is what it claims to be
Don't trust a README that says "run this" — check the same things you would for any third-party image: which CPU archs are actually in the manifest, and that the binary inside answers a --version.
With stock tools:
# what's actually in the manifest (needs buildx or `docker manifest`)
docker manifest inspect ghcr.io/whisper-sec/whisper:latest | jq '.manifests[].platform'
# -> {"architecture":"amd64","os":"linux"}
# {"architecture":"arm64","os":"linux"}
# pull and run it — proves the binary executes on your arch
docker run --rm ghcr.io/whisper-sec/whisper --version
# -> whisper 0.128.0 (linux/amd64)
# who signed the manifest push / what digest are you actually running
docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/whisper-sec/whisper:latest
# -> ghcr.io/whisper-sec/whisper@sha256:...
With Whisper: there's nothing Whisper-specific to run here — verifying an OCI image is a Docker/OCI-spec operation, not a Whisper API, which is the point: the same docker manifest inspect / docker run --version pattern you'd use on any third-party image is all you need. Pin by digest (ghcr.io/whisper-sec/whisper@sha256:...) rather than :latest in anything that matters — the tag moves, the digest doesn't.
Three run-modes behind one entrypoint
The image is one artifact; what it does is picked by the arguments after it, exactly like the native binary.
1. Plain CLI — one-shot commands
docker run --rm ghcr.io/whisper-sec/whisper verify 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
# -> DNSSEC chain valid, PTR matches forward, TLSA present — same keyless check as `whisper verify` anywhere else
No API key needed for verify/rdap — see Verify an agent for what the check actually walks (DNSSEC → PTR → forward A/AAAA → TLSA, RFC 4035 / RFC 6698). Mount a key in for the control-plane half:
docker run --rm -e WHISPER_API_KEY=whisper_live_... ghcr.io/whisper-sec/whisper list
# -> the agents registered under that key
2. MCP server — stdio, for any MCP-speaking agent host
docker run -i --rm -e WHISPER_API_KEY=whisper_live_... ghcr.io/whisper-sec/whisper mcp
This is the container form of the registry entry io.github.whisper-sec/whisper — same tool set (keyless verify/rdap; keyed register/list/policy/logs/revoke/egress-config), just running as a container instead of a locally-installed binary. Point Claude Code, Zed, or any MCP client's config at docker run -i --rm ghcr.io/whisper-sec/whisper mcp as the command instead of a bare whisper mcp if you'd rather not install the CLI on the host at all — see MCP server.
3. Egress sidecar — the mode Kubernetes wants
Run the image as a long-lived connect sidecar; it holds the API key and exposes a loopback SOCKS5 port — exactly the shape the Kubernetes operator injects into a pod.
docker run -d --name whisper-egress \
-e WHISPER_API_KEY=whisper_live_... \
ghcr.io/whisper-sec/whisper connect my-agent --tier socks5
Give the app container the same network namespace as the sidecar (Docker --network container:whisper-egress, or the shared-loopback pod model in Kubernetes) so it reaches the proxy on localhost, and point ALL_PROXY at it. Traffic then egresses from my-agent's routable /128 — the same Tier 1.5 mechanism (AnyIP + IP_FREEBIND) described in Connect & egress, just running as a long-lived container next to your app instead of inline in the same process. The app image needs no Whisper code and never handles the bearer — the sidecar does, and the app only ever sees a loopback proxy.
With stock tools, from a container sharing the sidecar's netns:
docker run --rm --network container:whisper-egress curlimages/curl \
curl -x socks5h://localhost:1080 -s https://api64.ipify.org
# -> 2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4
With Whisper, whisper run inside the app container does the same proxy-env wiring plus a pre-flight egress check in one step — see the whisper connect/whisper run walkthrough in Connect & egress.
Compose — app + sidecar in one file
services:
whisper-egress:
image: ghcr.io/whisper-sec/whisper:latest
environment:
WHISPER_API_KEY: whisper_live_...
command: ["connect", "my-agent", "--tier", "socks5"]
agent:
image: my-agent:latest
network_mode: "service:whisper-egress" # share the sidecar's netns → reach it on loopback
environment:
ALL_PROXY: socks5h://localhost:1080
depends_on: [whisper-egress]
docker compose up gives you an agent process that talks to the world through a routable /128 without a single line of proxy-handling code in the app image — the ALL_PROXY env var is what curl, Python's requests/httpx, Go's net/http, and Claude Code already read natively (Node's global fetch needs undici's EnvHttpProxyAgent wired in — one line, since it doesn't pick up proxy env vars on its own).
Where this fits next to the operator and the raw CLI
The GHCR image is the building block; two other channels consume it rather than duplicate it:
- Kubernetes — the
whisper-sec/whisper-operatorcontroller injects this exact image as a sidecar via a mutating admission webhook, so opted-in pods get egress with a namespace label instead of a hand-written manifest. If you're already running the operator, you don't need the recipes above at all; if you're not on Kubernetes (or not ready to install a CRD), the raw image + Compose pattern above is the same mechanism with none of the cluster machinery. - CLI & one-command setup — if the host does let you install a binary (a normal VM, a laptop, a CI image you control),
curl -fsSL https://get.whisper.online/install.sh | shor the platform package managers are simpler than pulling a container for a single command. Reach for the image specifically when you can't or don't want to touch the host's package state — CI runners, hardened base images, or anywhere "no extra installed packages" is itself a security requirement.
Every path — native binary, container, or Kubernetes sidecar — is the same two-tier contract: no key still gets verify/rdap for free (real value, zero friction); a key unlocks register/list/policy/logs/revoke/egress. The full source for the image build lives in whisper-sec/whisper-cli; status of every distribution channel, this one included, is tracked live at whisper.online/integrations.
Next
Kubernetes — the operator that injects this image as a sidecar automatically · CLI & one-command setup — the same binary installed directly on a host.