Skip to content
docktionary

Snippets / CI/CD

GitLab CI: build, scan, push

Builds a container image, pushes it to GitLab's own registry, and scans it with GitLab's built-in Container Scanning.

gitlab-ciciregistry
.gitlab-ci.yml
include:
  # GitLab's own Trivy-based scan -- same idea as the trivy-action step
  # in the GitHub Actions version of this, built into GitLab instead of
  # a separate step you add yourself.
  - template: Jobs/Container-Scanning.gitlab-ci.yml

build:
  stage: build
  image: docker:29
  # docker-in-docker needs a runner with privileged mode enabled. If
  # yours doesn't have that, build with BuildKit or Buildah instead --
  # GitLab's docs cover both as non-privileged alternatives.
  services:
    - docker:29-dind
  variables:
    # TLS between this job's docker client and the dind service --
    # required whenever both use a matching docker:*-dind pair.
    DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    # CI_REGISTRY_USER/PASSWORD are set automatically for every job --
    # nothing to create or rotate for pushing to the project's own
    # registry. --password-stdin keeps the token out of the process
    # list and shell history, unlike a plain -p flag.
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
  script:
    # Tagged by commit SHA, not "latest" -- every build is traceable
    # back to the exact source it was built from.
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'

container_scanning:
  variables:
    # Tell the included scan job which image to actually pull and scan --
    # by default it looks for CI_APPLICATION_REPOSITORY/TAG instead.
    CS_IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'