DrydockDrydock
ConfigurationUpdate Bouncer

Update Bouncer

Run security scanning, signature verification, and SBOM generation before applying container updates.

Update Bouncer runs security scanning in a safe-pull flow:

  1. Candidate image is scanned before update
  2. Update is blocked when CVEs match configured blocking severities
  3. Scan result is stored in container.security.scan and exposed in API/UI

Enablement

Security scanning is disabled by default. To enable it, set:

DD_SECURITY_SCANNER=trivy

Variables

Env varRequiredDescriptionSupported valuesDefault value when missing
DD_SECURITY_SCANNER🔴Enable scanner providertrivydisabled
DD_SECURITY_BLOCK_SEVERITYBlocking severities (comma-separated). Set to NONE for advisory-only mode (scan without blocking updates)NONE, or any of UNKNOWN,LOW,MEDIUM,HIGH,CRITICALCRITICAL,HIGH
DD_SECURITY_TRIVY_SERVERTrivy server URL (enables client/server mode)URLempty (local CLI mode)
DD_SECURITY_TRIVY_COMMANDTrivy command path for local CLI mode (must not contain shell metacharacters or .. path traversal)executable pathtrivy
DD_SECURITY_TRIVY_TIMEOUTTrivy command timeout in millisecondsinteger (>=1000)120000
DD_SECURITY_SCAN_CRONCron expression for scheduled background security scanscron expressiondisabled
DD_SECURITY_SCAN_JITTERRandom jitter delay (ms) before each scheduled scan startsinteger (>=0)60000
DD_SECURITY_SCAN_CONCURRENCYMax digest scans processed in parallel during scheduled scansinteger (>=1)4
DD_SECURITY_SCAN_BATCH_TIMEOUTTotal scheduled scan batch timeout in milliseconds (0 disables timeout)integer (>=0)1800000
DD_SECURITY_SCAN_DIGEST_CACHE_MAX_ENTRIESMax in-memory digest scan cache entries (LRU eviction -- least recently used entries are removed when the limit is reached)integer (>0)500

Trivy modes

Client mode (local CLI)

Use this mode when the trivy binary is available inside the drydock runtime.

As of v1.3.0, the official drydock image includes both trivy and cosign. No custom image is needed for local CLI mode.
services:
  drydock:
    image: codeswhat/drydock:latest
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_BLOCK_SEVERITY=CRITICAL,HIGH
      - DD_SECURITY_TRIVY_COMMAND=trivy
      - DD_SECURITY_TRIVY_TIMEOUT=120000

Server mode (Trivy server)

Use this mode when running a separate Trivy server and letting drydock call it.

services:
  trivy:
    image: aquasec/trivy:latest
    command: server --listen 0.0.0.0:4954

  drydock:
    image: codeswhat/drydock:latest
    depends_on:
      - trivy
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_BLOCK_SEVERITY=CRITICAL,HIGH
      - DD_SECURITY_TRIVY_SERVER=http://trivy:4954
      - DD_SECURITY_TRIVY_TIMEOUT=120000

Advisory-Only Mode

Set DD_SECURITY_BLOCK_SEVERITY=NONE to run vulnerability scans without blocking updates. Scan results remain visible in the Security view and audit log, but no update is ever rejected due to detected vulnerabilities.

services:
  drydock:
    image: codeswhat/drydock:latest
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_BLOCK_SEVERITY=NONE

Signature Verification (cosign)

When enabled, candidate images are verified with cosign before the update proceeds. Updates are blocked if signatures are missing, invalid, or verification fails.

Env varRequiredDescriptionSupported valuesDefault value when missing
DD_SECURITY_VERIFY_SIGNATURESEnable signature verification gatetrue / falsefalse
DD_SECURITY_COSIGN_KEYPath to cosign public key filefile pathempty (keyless / Sigstore)
DD_SECURITY_COSIGN_COMMANDCosign command pathexecutable pathcosign
DD_SECURITY_COSIGN_TIMEOUTCosign command timeout in millisecondsinteger (>=1000)60000
DD_SECURITY_COSIGN_IDENTITYCertificate identity for keyless verificationstringempty
DD_SECURITY_COSIGN_ISSUEROIDC issuer for keyless verificationstringempty
When DD_SECURITY_COSIGN_KEY is empty, cosign runs in keyless mode using Sigstore's public transparency log. Set DD_SECURITY_COSIGN_IDENTITY and DD_SECURITY_COSIGN_ISSUER to constrain keyless verification to a specific signer.
The examples below use a direct Docker socket mount for brevity. For production deployments, use a socket proxy instead — all security features work identically with proxy-based connections.

Key-based verification

services:
  drydock:
    image: codeswhat/drydock:latest
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_VERIFY_SIGNATURES=true
      - DD_SECURITY_COSIGN_KEY=/keys/cosign.pub
    volumes:
      - ./cosign.pub:/keys/cosign.pub:ro
      - /var/run/docker.sock:/var/run/docker.sock

Keyless verification (Sigstore)

services:
  drydock:
    image: codeswhat/drydock:latest
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_VERIFY_SIGNATURES=true
      - DD_SECURITY_COSIGN_IDENTITY=https://github.com/CodesWhat/drydock/.github/workflows/release.yml@refs/tags/*
      - DD_SECURITY_COSIGN_ISSUER=https://token.actions.githubusercontent.com
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

SBOM Generation

When enabled, Trivy generates Software Bill of Materials (SBOM) documents for candidate images during the Update Bouncer flow. SBOMs are persisted in container.security.sbom and available via the API.

Env varRequiredDescriptionSupported valuesDefault value when missing
DD_SECURITY_SBOM_ENABLEDEnable SBOM generationtrue / falsefalse
DD_SECURITY_SBOM_FORMATSComma-separated list of SBOM formatsspdx-json, cyclonedx-jsonspdx-json
services:
  drydock:
    image: codeswhat/drydock:latest
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_SBOM_ENABLED=true
      - DD_SECURITY_SBOM_FORMATS=spdx-json,cyclonedx-json
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
SBOM documents are retrievable per-container via GET /api/containers/:id/sbom?format=\{format\} where format is one of spdx-json or cyclonedx-json.

Scheduled scanning

Set DD_SECURITY_SCAN_CRON to automatically scan all watched containers on a schedule. A random jitter delay (DD_SECURITY_SCAN_JITTER, default 60 seconds) is applied before each cycle to spread load. You can tune parallelism with DD_SECURITY_SCAN_CONCURRENCY (default 4) and cap total batch runtime with DD_SECURITY_SCAN_BATCH_TIMEOUT (default 1800000, set 0 to disable).

Digest-level scan dedup caching uses an interval derived from the cron schedule:

  • drydock parses DD_SECURITY_SCAN_CRON and uses the shortest upcoming gap between scheduled runs as cache TTL.
  • For irregular schedules (for example 0 3,9 * * *), cache TTL is based on the shortest gap (6h in this case), not a fixed daily fallback.
  • If interval derivation fails, drydock falls back to 24h.
services:
  drydock:
    image: codeswhat/drydock:latest
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_SCAN_CRON=0 3 * * *   # every day at 3 AM
      - DD_SECURITY_SCAN_JITTER=60000      # up to 60s random delay
      - DD_SECURITY_SCAN_CONCURRENCY=4     # scan up to 4 digests in parallel
      - DD_SECURITY_SCAN_BATCH_TIMEOUT=1800000 # abort remaining digest queue after 30m

On-demand scanning

You can trigger a security scan for any individual container without waiting for the next watch cycle or scheduled scan.

  • UI: Click the shield button on a container row to start a scan.
  • API: POST /api/containers/:id/scan runs vulnerability scanning, signature verification (if configured), and SBOM generation (if configured) on demand.

The endpoint is rate-limited to 30 requests per minute. Real-time progress is broadcast via SSE events dd:scan-started and dd:scan-completed so the UI updates automatically.

Dual-slot scanning

When a container has an available update, clicking Scan Now (or calling POST /api/containers/:id/scan) scans both the current running image and the available update image in a single operation.

  • Results for the current image are stored in container.security.scan
  • Results for the update image are stored in container.security.updateScan
  • The UI shows delta comparison badges indicating how vulnerabilities change between versions (e.g. +3 fixed, -1 new)

This differs from the pre-update Update Bouncer flow, which only scans the candidate image as a gate before applying an update. Dual-slot scanning is informational and does not block updates.

Full example (scanning + signatures + SBOM)

services:
  trivy:
    image: aquasec/trivy:latest
    command: server --listen 0.0.0.0:4954

  drydock:
    image: codeswhat/drydock:latest
    depends_on:
      - trivy
    environment:
      - DD_SECURITY_SCANNER=trivy
      - DD_SECURITY_BLOCK_SEVERITY=CRITICAL,HIGH
      - DD_SECURITY_TRIVY_SERVER=http://trivy:4954
      - DD_SECURITY_VERIFY_SIGNATURES=true
      - DD_SECURITY_COSIGN_IDENTITY=https://github.com/CodesWhat/drydock/.github/workflows/release.yml@refs/tags/*
      - DD_SECURITY_COSIGN_ISSUER=https://token.actions.githubusercontent.com
      - DD_SECURITY_SBOM_ENABLED=true
      - DD_SECURITY_SBOM_FORMATS=spdx-json,cyclonedx-json
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

On this page