The scan worker. It consumes queued scans, runs the engine, and writes findings. It serves no HTTP traffic and nothing connects to it.

Synopsis

No arguments, no flags, no subcommands. Configuration is read from the process environment.

Building and running it

In the container image the binary is at /app/worker. The image ships both binaries and defaults to the API, so a worker container overrides the command:
That line is the entire difference between an API container and a worker container — the image is the same one.

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=2 is 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 on SIGINT 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.

Scaling

Add processes. The worker holds no state that another worker needs, so scaling out is running more of them; see Scaling scans.