How to perform kaniko Docker build and push in separate GitLab CI stages?

kmindi picture kmindi · Jun 30, 2020 · Viewed 7.6k times · Source

I have a Dockerfile which I can build using kaniko in the GitLab CI/CD pipeline. Currently the build stage both builds the Container and pushes it to the remote Docker repository.

I would like to utilize the stages concept of the CI/CD pipeline to build the image, then perform automatic tests and run a container security analysis tool (Trivy) and then as the last step, if all before steps were successful, I want to have it pushed to the registry:

  1. Build Image
  2. Perform automatic tests (based on the created image)
  3. Analyse security of created image (using Trivy)
  4. Push the image to the registry only if previous steps were successful and don't rebuild image

The command to build and push the image is:

build:latest-master:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  script:
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --cache=true --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:latest
  only:
    - master

There is an option / command line flag to perform no push with --no-push and there is a flag --tar-path that only produces a tarball of the image.

How would I have to combine these flags and commands to create the image only without pushing it to the regsitry, as it should only be pushed there if the security check has been performed. And then how does the push stage (GitLab CI Job) look like, especially the exact kaniko command line.

It would be great if that last pushing stage/job could reuse the previously build image or cache and not rebuilt it again. I guess the tarball could be used somehow but what would be the flag for kaniko to use it? Or do I just use that tarball and use a docker command to push the tarball to the registy?

Answer

Guillaume picture Guillaume · Aug 19, 2020

You can do that using crane tool:

  • First step: Build with Kaniko and export to a tarball. Save your image as an artifact.
  • Second step: Push tarball to your registry using crane
docker:build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug-v1.0.0
    entrypoint: [""]
  script:
  - /kaniko/executor
    --context $CI_PROJECT_DIR
    --dockerfile $CI_PROJECT_DIR/docker/Dockerfile
    --no-push
    --destination $CI_REGISTRY_IMAGE/path/to/your/image:version
    --tarPath image.tar
  artifacts:
    paths:
    - image.tar
    when: on_success

docker:push:
  stage: push
  image:
    name: gcr.io/go-containerregistry/crane:debug
    entrypoint: [""]
  script:
  - crane auth login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  - crane push image.tar $CI_REGISTRY_IMAGE/path/to/your/image:version
  needs:
  - docker:build