Synopsis
Building and running it
/app/worker. The image ships both
binaries and defaults to the API, so a worker container overrides the command:
Environment it reads
See Scanning and concurrency for how to choose
a concurrency, and Vulnerability
database for the provider choice
and what it means for an air-gapped deployment.
What it needs on disk
The cache directory is the one piece of state a worker wants to keep across restarts. It holds the vulnerability database and unpacked image blobs, and it is the difference between a re-scan taking seconds and taking minutes. It does not need to be shared between workers and it does not need to survive a node failure — a cold worker rebuilds it, slowly. Give each worker its own persistent volume:What it does not need
No container runtime, and no Docker socket. The scanner resolves images from remote registries only, so there is nothing for a runtime socket to provide. Mounting one would be worse than useless: it is root on the host, granted to the process that handles the most untrusted input in the system, and it would let a caller-supplied image reference resolve against a local image store that may hold another tenant’s image. If you are adapting a deployment manifest that mounts/var/run/docker.sock,
remove that mount.
Leases, and why a lost worker is not a lost scan
A worker claims a scan under a lease and heartbeats while it works. If the process dies, the heartbeat stops, the lease expires, and a reaper requeues the scan for another worker.
The practical consequences:
- Killing a worker costs at most one lease interval, not the scans it was running. They are picked up again once the lease expires.
- A scan cannot outlive its lease. The run is bounded by it, because continuing past the point where another worker has already been handed the same job would mean two workers scanning it and one of them writing a result nobody is waiting for.
- Concurrency is per process. Three workers at
SCAN_CONCURRENCY=2is six concurrent scans. A per-tenant bound from each organisation’s plan applies on top, so one busy organisation cannot occupy the whole fleet.
Shutdown
The process stops onSIGINT or SIGTERM. It stops claiming new work
immediately; scans already running are abandoned rather than drained, and
recovered through the lease mechanism above.
That is the deliberate trade: draining would mean waiting up to the full scan
timeout — ten minutes by default — before a deploy could proceed. Recovery
costs one lease interval and needs no cooperation from a process that may
already be gone.

