CI/CD Pipeline with Kaniko and Trivy

In this article, we will set up a GitLab CI/CD pipeline that builds a Docker image using Kaniko, runs automated tests, performs a security scan with Trivy, and finally pushes the image to a Docker registry only if all previous steps are successful.

Pipeline Stages

The pipeline will consist of the following stages:

  1. Build Image: Create the Docker image.
  2. Run Tests: Execute automated tests on the built image.
  3. Security Analysis: Analyze the image for vulnerabilities using Trivy.
  4. Push to Registry: Push the image to the Docker registry if all previous steps pass.

GitLab CI Configuration

Here’s how you can configure your .gitlab-ci.yml file:

stages:
  - build
  - test
  - scan
  - push

build_image:
  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 --no-push
  only:
    - master

run_tests:
  stage: test
  script:
    - echo "Running tests..."
    # Add your test commands here

scan_image:
  stage: scan
  image: aquasec/trivy:latest
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:latest

push_image:
  stage: push
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  script:
    - /kaniko/executor --cache=true --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:latest
  only:
    - master
  when: on_success

Explanation of the Configuration

  • Build Stage: The build_image job builds the Docker image using Kaniko without pushing it to the registry (using the --no-push flag). This allows us to perform further checks before the image is stored.
  • Test Stage: The run_tests job is where you can add your automated testing commands to ensure the image works as expected.
  • Scan Stage: The scan_image job uses Trivy to scan the built image for vulnerabilities. If vulnerabilities are found, the job will exit with a non-zero status, preventing the push stage from executing.
  • Push Stage: The push_image job will only run if all previous jobs succeed. It uses Kaniko to push the image to the Docker registry.

Conclusion

By structuring your GitLab CI/CD pipeline in this way, you ensure that your Docker images are built, tested, and scanned for security vulnerabilities before being pushed to your registry, enhancing your deployment's security posture.