# Docker Image Ops

Scan, push and promote Docker images, with optional delayed mirroring (quarantine) for supply-chain protection.

## YAML Parameters

```typescript
interface YAMLParameters {
  /** Source image to scan and/or copy. Use registry `ACTION` to take the image built by a previous action. */
  src: ImageOpsSrcYaml;
  type: "DOCKER_IMAGE_OPS";
  /** Unique identifier for the action within the pipeline. */
  action: string;
  /** Destination to copy the image to. Omit to only scan. Set `quarantine` (days) for delayed mirroring. */
  push?: ImageOpsPushYaml;
  /** Trivy scan configuration (scanners, severities, ignore rules). Omit to skip scanning. */
  scan?: ImageOpsScanYaml;
  /** Specifies when the action should be executed. */
  trigger_time?: "ON_EVERY_EXECUTION" | "ON_SUCCESS" | "ON_FAILURE" | "ON_BACK_TO_SUCCESS" | "ON_WARNING" | "ON_WAIT_FOR_APPROVE" | "ON_TERMINATE";
  /** The list of variables for dynamic action execution. The action runs once for each value. */
  loop?: string[];
  /** Defines whether the action should be executed on each failure. Restricted to and required if the trigger_time is ON_FAILURE. */
  run_only_on_first_failure?: boolean;
  /** When set to true the action is disabled. By default it is set to false. */
  disabled?: boolean;
  /** The timeout in seconds. */
  timeout?: number;
  /** If set to true the execution will proceed, mark action as a warning and jump to the next action. Doesn't apply to deployment actions. */
  ignore_errors?: boolean;
  /** Delay time between auto retries in seconds. */
  retry_interval?: number;
  /** Number of retries if the action fails. */
  retry_count?: number;
  /** Defines whether the action should run in parallel with the next one. */
  run_next?: "WAIT_ON_SUCCESS" | "IN_SOFT_PARALLEL" | "IN_HARD_PARALLEL";
  /** The list of trigger conditions to meet so that the action can be triggered. */
  trigger_conditions?: TriggerConditionYaml[];
  /** The list of variables you can use in the action. */
  variables?: VariableYaml[];
}
```

## Type Definitions

```typescript
interface ImageOpsSrcYaml {
  /** Registry the source image lives in (e.g. `DOCKER_HUB`, `AMAZON_ECR`, `OTHER`), or `ACTION` to take the image built by a previous action. */
  docker_registry?: "ACTION" | "DOCKER_HUB" | "AMAZON_ECR" | "GOOGLE_GCR" | "GOOGLE_ARTIFACT_REGISTRY" | "ARTIFACT_REGISTRY" | "GIT_HUB_CONTAINER_REGISTRY" | "DIGITAL_OCEAN_CONTAINER_REGISTRY" | "OTHER";
  /** Host of a custom (`OTHER`) source registry (e.g. `registry.example.com`). Required when `docker_registry` is `OTHER`. */
  registry?: string;
  /** Region of the source registry. Required for region-scoped registries such as Amazon ECR. */
  region?: string;
  /** Identifier of the integration used to authenticate to a private source registry. */
  integration?: string;
  /** Source image name, optionally with a path (e.g. `library/node`). Ignored when `docker_registry` is `ACTION`. */
  image?: string;
  /** Source image tag (e.g. `20`, `latest`). Defaults to `latest` when omitted. */
  tag?: string;
  /** Name of the previous action whose built image is used as the source. Optional when `docker_registry` is `ACTION` — if omitted, the image built by the immediately preceding Docker build action is used. */
  from_action?: string;
  /** Username for a custom (`OTHER`) source registry that authenticates with credentials instead of an integration. */
  login?: string;
  /** Password for a custom (`OTHER`) source registry. Stored encrypted. */
  password?: string;
}

interface ImageOpsPushYaml {
  /** Registry to copy the image to (e.g. `DOCKER_HUB`, `AMAZON_ECR`, `OTHER`). */
  docker_registry?: "NONE" | "DOCKER_HUB" | "AMAZON_ECR" | "GOOGLE_GCR" | "GOOGLE_ARTIFACT_REGISTRY" | "OTHER" | "GIT_HUB_CONTAINER_REGISTRY" | "ARTIFACT_REGISTRY" | "DIGITAL_OCEAN_CONTAINER_REGISTRY";
  /** Host of a custom (`OTHER`) destination registry (e.g. `registry.example.com`). Required when `docker_registry` is `OTHER`. */
  registry?: string;
  /** Region of the destination registry. Required for region-scoped registries such as Amazon ECR. */
  region?: string;
  /** Identifier of the integration used to authenticate to the destination registry. */
  integration?: string;
  /** Destination image name. Omit to keep the source image name. */
  name?: string;
  /** Destination image tag. Omit to keep the source image tag. */
  tag?: string;
  /** Quarantine period in days. The image is mirrored to the destination only after the same digest has been seen for this many days (supply-chain delay). Omit to push immediately. */
  quarantine?: number;
  /** When `true`, skips TLS verification when talking to the registries. Default: `false`. */
  insecure_registry?: boolean;
}

interface ImageOpsScanYaml {
  /** Enabled Trivy scanners (e.g. `VULNERABILITY`, `SECRET`, `MISCONFIGURATION`, `LICENSE`). */
  scanners?: string[];
  /** Severity levels that trigger reporting/failure (e.g. `CRITICAL`, `HIGH`). */
  severities?: string[];
  /** When `true`, the action fails only when a finding has a fix available. Default: `false`. */
  fail_only_on_fixable?: boolean;
  /** Rules that suppress specific findings from the scan report, keyed by finding category. */
  ignore?: IgnoreYaml;
}

interface TriggerConditionYaml {
  /** The type of trigger condition */
  trigger_condition: "ALWAYS" | "ON_CHANGE" | "ON_CHANGE_AT_PATH" | "VAR_IS" | "VAR_IS_NOT" | "VAR_CONTAINS" | "VAR_NOT_CONTAINS" | "DATETIME" | "SUCCESS_PIPELINE" | "DAY" | "HOUR" | "OR" | "VAR_LESS_THAN" | "VAR_LESS_THAN_OR_EQUAL" | "VAR_GREATER_THAN" | "VAR_GREATER_THAN_OR_EQUAL" | "ACTION_STATUS_IS" | "ACTION_STATUS_IS_NOT" | "TRIGGERING_USER_IS" | "TRIGGERING_USER_IS_NOT" | "TRIGGERING_USER_IS_IN_GROUP" | "TRIGGERING_USER_IS_NOT_IN_GROUP";
  /** The value to compare the trigger variable against */
  trigger_variable_value?: string;
  /** The name of the variable to check in the trigger condition */
  trigger_variable_key?: string;
  /** The timezone for datetime trigger conditions (e.g., 'UTC', 'Europe/Warsaw') */
  timezone?: string;
  /** The hours when the datetime trigger should activate (0-23) */
  trigger_hours?: number[];
  /** The days when the datetime trigger should activate (1-7, where 1 is Monday) */
  trigger_days?: number[];
  /** The project name for cross-project pipeline triggers */
  project?: string;
  /** The pipeline name for cross-pipeline triggers */
  pipeline?: string;
  /** The email of the user who can trigger the pipeline */
  trigger_user?: string;
  /** The name of the group that can trigger the pipeline */
  trigger_group?: string;
  /** The file paths that must change to trigger the pipeline */
  trigger_condition_paths?: string[];
  /** The action status to check for action status triggers */
  trigger_status?: "SUCCESSFUL" | "FAILED" | "SKIPPED" | "SUPPRESSED";
  /** The name of the action to check status for */
  trigger_action_name?: string;
  /** The list of nested trigger conditions for OR/AND operators */
  trigger_operands?: TriggerConditionYaml[];
}

interface VariableYaml {
  /** The name of the variable */
  key: string;
  /** The value of the variable */
  value?: string;
  /** The type of the added variable */
  type?: "VAR" | "FILE" | "SSH_KEY" | "IOS_KEYCHAIN" | "IOS_PROVISION_PROFILES" | "SSH_PUBLIC_KEY" | "GPG_KEY";
  /** If set to true the variable value will be encrypted and hidden */
  encrypted?: boolean;
  /** The optional description of the variable */
  description?: string;
  /** Initial path for the variable */
  init_path?: string;
  /** Default value for the variable */
  defaults?: string;
  /** Specifies where to copy the file on each run. Set if type is FILE, SSH_KEY, IOS_KEYCHAIN, or IOS_PROVISION_PROFILES. */
  file_path?: string;
  /** File permission set on copy to a container on each run. Set if type is FILE, SSH_KEY, IOS_KEYCHAIN, or IOS_PROVISION_PROFILES. */
  file_chmod?: string;
  /** Set if type is FILE, SSH_KEY, IOS_KEYCHAIN, or IOS_PROVISION_PROFILES. If it's NONE, the variable can be used as a parameter in an action. For CONTAINER, the given key is additionally copied to an action container on each run */
  file_place?: "NONE" | "CONTAINER";
  /** Password for certificates */
  password?: string;
  /** Passphrase for encrypted SSH keys */
  passphrase?: string;
  /** Key identifier for iOS certificates, provisioning profiles, or GPG keys */
  key_identifier?: string;
  /** If set to true the variable value can be set by Buddy actions */
  settable?: string;
  /** If set to true the variable is disabled and will not be injected anywhere */
  disabled?: boolean;
  /** Encoding of the variable value. Use `b64` for binary files (certificates, images, compiled blobs) where the value is already base64-encoded. Omit or set to `text` for plain text files (JSON, XML, config) — the system will handle encoding automatically. Only applies to non-encrypted asset variables (FILE, SSH_KEY, SSH_PUBLIC_KEY, IOS_KEYCHAIN, IOS_PROVISION_PROFILES). */
  encoding?: "text" | "b64";
}

```

## YAML Examples

### Scan an image produced by the previous action

```yaml
  - action: "Docker image ops"
    type: "DOCKER_IMAGE_OPS"
    src:
      docker_registry: "ACTION"
      from_action: "Build Docker image"
    scan:
      scanners:
        - "VULNERABILITY"
        - "SECRET"
      severities:
        - "CRITICAL"
        - "HIGH"

```

### Scan the image built by the immediately preceding action

```yaml
  - action: "Docker image ops"
    type: "DOCKER_IMAGE_OPS"
    src:
      docker_registry: "ACTION"
    scan:
      scanners:
        - "VULNERABILITY"
      severities:
        - "CRITICAL"
        - "HIGH"

```

### Scan and push an image built by a previous action

```yaml
  - action: "Docker image ops"
    type: "DOCKER_IMAGE_OPS"
    src:
      docker_registry: "ACTION"
      from_action: "Build Docker image"
    push:
      docker_registry: "ARTIFACT_REGISTRY"
      name: "my-app"
      tag: "1.0.0"
    scan:
      scanners:
        - "VULNERABILITY"
      severities:
        - "CRITICAL"
        - "HIGH"

```

### Scan and promote an image to a new tag in the same registry

```yaml
  - action: "Docker image ops"
    type: "DOCKER_IMAGE_OPS"
    src:
      docker_registry: "DOCKER_HUB"
      integration: "docker-hub"
      image: "my-org/my-app"
      tag: "staging"
    push:
      docker_registry: "DOCKER_HUB"
      integration: "docker-hub"
      name: "my-org/my-app"
      tag: "production"
    scan:
      scanners:
        - "VULNERABILITY"
      severities:
        - "CRITICAL"

```

### Delayed mirror with quarantine, scan and ignore rules

```yaml
  - action: "Docker image ops"
    type: "DOCKER_IMAGE_OPS"
    src:
      docker_registry: "DOCKER_HUB"
      image: "node"
      tag: "20"
    push:
      docker_registry: "AMAZON_ECR"
      region: "us-east-1"
      integration: "my-ecr"
      quarantine: 14
    scan:
      scanners:
        - "VULNERABILITY"
        - "SECRET"
        - "MISCONFIGURATION"
      severities:
        - "CRITICAL"
        - "HIGH"
      fail_only_on_fixable: true
      ignore:
        vulnerabilities:
          - id: "CVE-2023-45853"
            statement: "No upstream fix available, accepted risk"
            expires_at: "2026-09-21"
            paths:
            - "vendor/"

```


---
Original source: https://buddy.works/docs/yaml/yaml-actions/docker-image-ops