For the complete documentation index, see llms.txt. This page is also available as Markdown.

Build/scan/push pipelines for container images in STO

End-to-end pipeline examples for different use cases.

You generally want to scan any container images you build and then push them to your production registry only if the scan did not detect any serious vulnerabilities.

The following workflows provide some examples of you can set up pipelines to automate security checks for your images.

Build/scan/push with Docker-in-Docker

This workflow is useful if you can use Docker-in-Docker and don't have a CI license. For a hands-on example of how to implement this, go to (STO license) Create a build-scan-push pipeline .

  1. Add a Docker-in-Docker background step to your pipeline.

  2. Add a Run step to build a local copy of the container image.

  3. Add a Security Tests step to scan the snapshot image and ingest the results.

    If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails.

  4. Add a Run step that pushes the local image to your production container registry.

Example build/scan/push pipeline using Docker-in-Docker

pipeline:
  projectIdentifier: jsmithstosandbox
  orgIdentifier: default
  identifier: buildscanpushwithdind
  name: build_scan_push_with_dind
  tags: {}
  stages:
    - stage:
        name: build
        identifier: build
        type: SecurityTests
        spec:
          cloneCodebase: false
          execution:
            steps:
              - step:
                  type: Background
                  name: DinD
                  identifier: Background
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    image: docker:dind
                    shell: Sh
                    privileged: true
                    entrypoint:
                      - dockerd
              - step:
                  type: Run
                  name: build_image
                  identifier: build_image
                  spec:
                    connectorRef: YOUR_CONTAINER_IMAGE_REGISTRY_CONNECTOR_ID
                    image: docker
                    shell: Sh
                    command: |-

                      # wait until the dind service is available
                      while ! docker ps ;do
                            echo "Docker not available yet"
                      done
                      echo "Docker service is ready"

                      # install git, clone the code repo, and cd to the local clone
                      apk add git
                      git --version
                      git clone https://github.com/<+stage.variables.GITHUB_USERNAME>/<+stage.variables.GITHUB_REPO>
                      cd <+stage.variables.GITHUB_REPO>

                      # build and tag the local image
                      docker login --username="<+stage.variables.DOCKERHUB_USERNAME>" --password="<+stage.variables.DOCKERHUB_PAT>" 
                      docker build -t <+stage.variables.DOCKER_IMAGE_LABEL> .
                      docker tag <+stage.variables.DOCKER_IMAGE_LABEL> <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>:bsp-<+pipeline.sequenceId>

                    privileged: true
              - step:
                  type: AquaTrivy
                  name: scan_image
                  identifier: scan_image
                  spec:
                    mode: orchestration
                    config: default
                    target:
                      name: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                      type: container
                      variant: bsp-<+pipeline.sequenceId>
                    advanced:
                      log:
                        level: debug
                      fail_on_severity: none
                    privileged: true
                    image:
                      type: local_image
                      name: <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>
                      access_id: <+stage.variables.DOCKERHUB_USERNAME>
                      access_token: <+stage.variables.DOCKERHUB_PAT>
                      tag: bsp-<+pipeline.sequenceId>
              - step:
                  type: Run
                  name: push_image
                  identifier: push_image
                  spec:
                    connectorRef: CONTAINER_IMAGE_REGISTRY_CONNECTOR
                    image: docker
                    shell: Sh
                    command: |-

                      # if the image passed the scan,
                      # push it to the image registry
                      docker login --username="<+stage.variables.DOCKERHUB_USERNAME>" --password="<+stage.variables.DOCKERHUB_PAT>" 
                      docker push <+stage.variables.DOCKERHUB_USERNAME>/<+stage.variables.DOCKER_IMAGE_LABEL>:bsp-<+pipeline.sequenceId>
                    privileged: true
          sharedPaths:
            - /var/run
            - /var/lib/docker
          platform:
            os: Linux
            arch: Amd64
          runtime:
            type: Cloud
            spec: {}
          slsa_provenance:
            enabled: false
        variables:
          - name: DOCKERHUB_USERNAME
            type: String
            description: ""
            value: janesmith
          - name: DOCKERHUB_PAT
            type: Secret
            description: ""
            value: jsmith-dockerhub-pat
          - name: GITHUB_USERNAME
            type: String
            description: ""
            value: jane-smith
          - name: GITHUB_REPO
            type: String
            description: ""
            value: codebaseAlpha
          - name: GITHUB_PAT
            type: Secret
            description: ""
            value: jsmith-github-pat
          - name: DOCKER_IMAGE_LABEL
            type: String
            description: ""
            value: myalphaservice
        description: ""

Build/scan/push with CI and Docker-in-Docker

This workflow is useful if you can use Docker-in-Docker and have a CI license. For a hands-on example of how to implement this, go to Create a build-scan-push pipeline (STO and CI).

  1. Add a Docker-in-Docker background step to your pipeline.

  2. Add a CI Build and Push step to build and push your image with a snapshot tag such asimage:snapshot-donotuse-<+pipeline.executionId>.

  3. Add a Security Tests step to scan the snapshot image.

    If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails.

  4. Add a second CI Build and Push step to build and push your image with a release tag such asimage:<+pipeline.executionId>.

Example build/scan/push pipeline using CI and Docker-in-Docker

Build/scan/push with Kaniko

This workflow is useful if you don't have a CI license and want to use Kaniko (which doesn't require Privileged mode) instead of a Docker-in-Docker background step.

  1. In the Security stage overview, under Shared Paths, add a path on the stage volume where you can share the image TAR across steps.

  2. Use a Run step to build a local copy of the container image. The step should also save the TAR of the image to the shared path on the stage volume.

  3. Use a Run step to run a manual scan of the local image.

  4. Add a Security Tests step to ingest your scan data.

    If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails.

  5. Set up a Run step that uses kaniko to push the TAR file of the image to your production image registry.

Build/scan/push with CI and skopeo

This workflow is useful if you have a CI license and want to use skopeo (which doesn't require Privileged mode) instead of a Docker-in-Docker background step.

  1. In the Security stage overview, under Shared Paths, add a path on the stage volume where you can share the image TAR across steps.

  2. Use a CI Build and Push step to build and push your image with a snapshot tag such asimage:snapshot-<+pipeline.executionId>.

  3. Use a Run step that uses skopeo to pull the image TAR to your shared path.

  4. Use a Run step to scan the local image TAR.

  5. Add a Security Tests step to ingest your scan data.

    If the scan results meet or exceed the Fail on Severity threshold, the pipeline fails.

  6. Add a Run step that uses skopeo to push the image TAR (with an official tag) from the shared path to the container image registry.

Last updated

Was this helpful?