Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Push existing tarball image with kaniko

I want to build a Docker image (tarball) in my GitLab CI pipeline using kaniko, then scan it with trivy and push it to an AWS ECR using kaniko.

  • Step 1: kaniko build (tarball)
  • Step 2: trivy scan
  • Step 3: kaniko push (to AWS ECR!)

Unfortunately I can't find a way to push an existing tarball image with kaniko without rebuilding it.

I also tried crane for the push, but can't get a login due to the non-existent credHelper.

I don't actually want to do big installations, nor do I want to create a custom image for this.

Is this possible? What would be potential solutions?

like image 428
Stefan Avatar asked Sep 07 '25 18:09

Stefan


1 Answers

Coincidentally, I did exactly this a while ago. Here is how I did it:

docker:build:
  stage: build
  image:
    name: Kaniko image
    entrypoint: [""]
  script:
    - mkdir tar_images
    - mkdir -p /kaniko/.docker
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context ${CI_PROJECT_DIR} --no-push --destination $CI_REGISTRY/<image_name>:<image_tag> --tarPath tar_images/$file_name.tar
  artifacts:
    paths:
      - tar_images
    when: on_success
  # scan all built images
  # currently bug with grype as docker registry is not public!
docker:scan:
  stage: scan
  image:
    name: trivy
    entrypoint: [""]
  script:
    - mkdir scan_result
    - cd tar_images
    - |
      for tar_image in *.tar; 
      do
        [ -e "$tar_image" ] || continue;
        file_name=${tar_image%.*};
        echo $file_name;
        if [ "$vulnerability_scanner" = "trivy" ]; then
          trivy image --timeout 15m --offline-scan --input $tar_image -f json -o ../scan_result/$file_name.json --severity CRITICAL;
         fi
      done
  artifacts:
    paths:
      - scan_result
    expire_in: 1 month

# push all images without detected security issues
docker:push:
  stage: push
  image:
    name: gcr.io/go-containerregistry/crane:debug
    entrypoint: [""]
  rules:
    - if: $UPDATE
  script:
    - cd tar_images
    - |
      for tar_image in *.tar; 
      do 
        file_name=${tar_image%.*};
        vulnerabilities=`awk  -F '[:,]' '/"Vulnerabilities"/ {gsub("[[:blank:]]+", "", $2); print $2}' ../scan_result/$file_name.json`; # find vulnerabilities in json file
        if ! [ -z "$vulnerabilities" ]; then # if vulnerabilities found in image
          echo "There are security issues with the image $img.Dockerfile. Image is not pushed to registry!";
        else # push image
            crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY;
            crane push $tar_image $CI_REGISTRY_IMAGE/<image_name>:<image_tag>;
        fi
      done

What happens here is that in the first job the images are built using kaniko. They are stored as tar files and made accessible to the next job via artifacts. In the next job they are scanned using trivy and the scan results are stored as artifacts. Then the scan reports are analyzed and if no vulnerabilities had been detected the image is pushed using crane.

The code above probably does not work out of the box as I copied it out of a bigger yaml file.

like image 114
Moritz Avatar answered Sep 11 '25 02:09

Moritz