InfoGrab DocsInfoGrab Docs

멀티 컨테이너 스캐닝

요약

멀티 컨테이너 스캐닝을 사용하면 단일 파이프라인에서 여러 컨테이너 이미지를 스캔할 수 있습니다. 멀티 컨테이너 스캐닝은 동적 자식 파이프라인을 사용해 스캔을 동시에 실행하므로 전체 파이프라인 실행 시간이 줄어듭니다. 멀티 컨테이너 스캐닝은 다음을 지원합니다:

히스토리

멀티 컨테이너 스캐닝을 사용하면 단일 파이프라인에서 여러 컨테이너 이미지를 스캔할 수 있습니다. 이 기능으로 다음을 수행할 수 있습니다:

  • 여러 이미지를 병렬로 스캔합니다.
  • 단일 구성 파일에서 스캐닝 대상을 구성합니다.
  • 기존 컨테이너 스캐닝 워크플로와 통합합니다.

멀티 컨테이너 스캐닝은 동적 자식 파이프라인을 사용해 스캔을 동시에 실행하므로 전체 파이프라인 실행 시간이 줄어듭니다.

지원되는 이미지#

멀티 컨테이너 스캐닝은 다음을 지원합니다:

  • 공개 레지스트리(Docker Hub, GitLab Container Registry 등)의 이미지
  • 개인 레지스트리(인증이 구성된 경우)의 이미지
  • 멀티 아키텍처 이미지

멀티 컨테이너 스캐닝 켜기#

사전 요구 사항:

  • 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
  • Docker 실행기를 사용하는 GitLab Runner.
  • 리포지터리 루트의 .gitlab-multi-image.yml 구성 파일.
  • 스캔할 컨테이너 이미지 하나 이상.

멀티 컨테이너 스캐닝을 켜려면 다음 단계를 수행합니다:

  1. 리포지터리 루트에 .gitlab-multi-image.yml 파일을 생성합니다:

       scanTargets:
         - name: alpine
           tag: latest
         - name: python
           tag: 3.9-slim
    
  2. .gitlab-ci.yml에 템플릿을 포함합니다:

       include:
         - template: Jobs/Multi-Container-Scanning.latest.gitlab-ci.yml
    
  3. 변경 사항을 커밋하고 푸시합니다. 파이프라인이 자동으로 스캔을 실행합니다.

구성#

.gitlab-multi-image.yml 파일을 편집하여 멀티 컨테이너 스캐닝을 구성합니다.

기본 구성 예시#

scanTargets:
  - name: alpine
    tag: "3.19"
  - name: ubuntu
    tag: "22.04"

전체 구성 예시#

# Include license information in reports
includeLicenses: true

# Configure registry authentication
auths:
  registry.example.com:
    username: ${REGISTRY_USER}
    password: ${REGISTRY_PASSWORD}

# Allow insecure connections (not recommended for production)
allowInsecure: false

# Additional CA certificates for custom registries
additionalCaCertificateBundle: |
  -----BEGIN CERTIFICATE-----
  ...
  -----END CERTIFICATE-----

# Images to scan
scanTargets:
  - name: registry.example.com/myapp
    tag: "v1.2.3"
  - name: postgres
    tag: "15-alpine"

구성 옵션#

Note

멀티 컨테이너 스캐닝에서는 자식 job에 러너 태그를 지정할 수 없지만, 이슈 363687에서 이 동작을 변경할 것을 제안하고 있습니다.

옵션 유형 필수 여부 설명
scanTargets Array Yes 스캔할 컨테이너 이미지 목록
scanTargets[].name String Yes 이미지 이름(선택적 레지스트리 포함)
scanTargets[].tag String No 이미지 태그(기본값: latest)
scanTargets[].registry String No 레지스트리 재정의
includeLicenses Boolean No 보고서에 라이선스 정보 포함
auths Object No 레지스트리 인증 자격 증명
allowInsecure Boolean No 안전하지 않은 HTTPS 연결 허용
additionalCaCertificateBundle String No PEM 형식의 추가 CA 인증서

일반적인 시나리오#

다음 섹션에서는 필요에 맞게 응용할 수 있는 예시 시나리오를 설명합니다.

서로 다른 레지스트리의 이미지 스캔#

scanTargets:
  - name: docker.io/library/nginx
    tag: "1.25"
  - name: registry.gitlab.com/mygroup/myapp
    tag: "main"
  - name: gcr.io/myproject/service
    tag: "prod"

개인 레지스트리 인증 사용#

auths:
  registry.gitlab.com:
    username: ${CI_REGISTRY_USER}
    password: ${CI_REGISTRY_PASSWORD}
  docker.io:
    username: ${DOCKERHUB_USER}
    password: ${DOCKERHUB_TOKEN}

scanTargets:
  - name: registry.gitlab.com/private/image
    tag: latest

컴플라이언스를 위한 특정 버전 스캔#

scanTargets:
  - name: postgres
    tag: "14.10"
  - name: redis
    tag: "7.2.3"
  - name: nginx
    tag: "1.25.3"

동적으로 빌드된 이미지 스캔#

이미지 이름과 태그를 런타임에만 알 수 있는 경우, 정적 .gitlab-multi-image.yml 파일에 scanTargets를 정의할 수 없습니다.

이러한 이미지를 스캔하려면 multi-cs::generate-scan job을 재정의하여, 빌드 job 이 생성한 dotenv 아티팩트로부터 구성 파일을 동적으로 만듭니다:

include:
  - template: Jobs/Multi-Container-Scanning.latest.gitlab-ci.yml

.build-rules: &build-rules
  rules:
    - if: $CONTAINER_SCANNING_DISABLED == 'true' || $CONTAINER_SCANNING_DISABLED == '1'
      when: never
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

build-image-1:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  <<: *build-rules
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
    - export IMAGE1_NAME="$CI_REGISTRY_IMAGE/app1:$CI_COMMIT_SHORT_SHA-$CI_JOB_ID"
    - docker build -f Dockerfiles/Dockerfile.app1 -t "$IMAGE1_NAME" .
    - docker push "$IMAGE1_NAME"
    - echo "IMAGE1_NAME=$IMAGE1_NAME" >> build1.env
  artifacts:
    reports:
      dotenv: build1.env

build-image-2:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  <<: *build-rules
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
    - export IMAGE2_NAME="$CI_REGISTRY_IMAGE/app2:$CI_COMMIT_SHORT_SHA-$CI_JOB_ID"
    - docker build -f Dockerfiles/Dockerfile.app2 -t "$IMAGE2_NAME" .
    - docker push "$IMAGE2_NAME"
    - echo "IMAGE2_NAME=$IMAGE2_NAME" >> build2.env
  artifacts:
    reports:
      dotenv: build2.env

# Override the template job to inject the dynamically generated config
multi-cs::generate-scan:
  needs:
    - job: build-image-1
      artifacts: true
    - job: build-image-2
      artifacts: true
  before_script:
    - !reference [.multi-cs-generate-scan-base, before_script]  # preserve template steps if any
    - IMAGE1_REPO="${IMAGE1_NAME%:*}"
    - IMAGE1_TAG="${IMAGE1_NAME##*:}"
    - IMAGE2_REPO="${IMAGE2_NAME%:*}"
    - IMAGE2_TAG="${IMAGE2_NAME##*:}"
    - |
      cat > .gitlab-multi-image.yml <

CI/CD 변수#

CI/CD 변수를 사용하여 멀티 컨테이너 스캐닝 동작을 사용자 지정할 수 있습니다.

변수 기본값 설명
CONTAINER_SCANNING_DISABLED - 스캐닝을 비활성화하려면 true 또는 1로 설정
AST_ENABLE_MR_PIPELINES true 머지 리퀘스트 파이프라인에서 스캐닝 활성화
CS_SCANNER_IMAGE registry.gitlab.com/.../multiple-container-scanner:0 사용할 스캐너 이미지

멀티 컨테이너 스캐닝 비활성화#

스캐닝을 일시적으로 비활성화하려면 다음을 설정합니다:

variables:
  CONTAINER_SCANNING_DISABLED: "true"

MR 파이프라인 스캐닝 비활성화#

variables:
  AST_ENABLE_MR_PIPELINES: "false"

스캔 결과 보기#

사전 요구 사항:

  • 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
  • 프로젝트에 멀티 컨테이너 스캐닝이 켜져 있어야 합니다.
  • 컨테이너 스캐닝 결과를 포함한 파이프라인이 완료되어 있어야 합니다.

스캔 결과를 보려면 다음 단계를 수행합니다:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 머지 리퀘스트 또는 파이프라인 세부 정보 페이지로 이동합니다.
  3. Security 탭을 선택합니다.
  4. 스캔한 모든 이미지에서 감지된 취약점을 확인합니다.

스캔한 이미지마다 다음이 생성됩니다:

  • 컨테이너 스캐닝 보고서.
  • CycloneDX SBOM(소프트웨어 자재 명세서).
  • 라이선스 정보(includeLicenses: true인 경우).

파이프라인 구조#

멀티 컨테이너 스캐닝은 job 두 개를 생성합니다:

  • multi-cs::generate-scan: 스캐닝 구성을 생성합니다
  • multi-cs::trigger-scan: 병렬 스캔 job 이 포함된 자식 파이프라인을 트리거합니다

자식 파이프라인에는 scanTargets의 이미지마다 job 이 하나씩 포함됩니다.

문제 해결#

멀티 컨테이너 스캐닝을 사용할 때 다음 문제가 발생할 수 있습니다.

"configuration file not found" 파이프라인 실패#

원인: .gitlab-multi-image.yml 파일이 없거나 잘못된 위치에 있습니다.

해결 방법: .gitlab-multi-image.yml이 리포지터리 루트에 있는지 확인합니다.

개인 레지스트리 인증 실패#

원인: 잘못된 자격 증명이거나 인증 구성이 누락되었습니다.

해결 방법:

  1. 자격 증명이 올바르고 제대로 구성되어 있는지 확인합니다.

       auths:
         registry.example.com:
           username: ${REGISTRY_USER}
           password: ${REGISTRY_PASSWORD}
    
  2. Settings > CI/CD > Variables에서 변수를 정의합니다.

스캔이 너무 오래 걸림#

원인: 대용량 이미지 여러 개를 순차적으로 스캔하고 있습니다.

해결 방법: 멀티 컨테이너 스캐닝은 이미 스캔을 병렬로 실행합니다.

다음을 고려합니다:

  • 더 작은 기반 이미지 사용
  • 특정 이미지 버전만 스캔
  • GitLab Runner 동시성 설정 조정

자식 파이프라인에 보고서가 표시되지 않음#

원인: 트리거 구성에 strategy: mirror가 없습니다.

해결 방법: 템플릿에는 이 값이 기본적으로 구성되어 있습니다. 템플릿을 사용자 지정했다면 트리거 job에 strategy: mirror가 포함되어 있는지 확인합니다.

자식 파이프라인이 예상과 다른 러너에서 실행됨#

자식 파이프라인 job 이 예상하지 않은 러너에서 실행될 수 있습니다.

이 문제는 자식 파이프라인 job 이 부모 job의 러너 태그를 상속하지 않기 때문에 발생합니다. 이슈 363687에서 이 동작을 변경할 것을 제안하고 있습니다.

멀티 컨테이너 스캐닝

GitLab v19.5
Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기

요약

멀티 컨테이너 스캐닝을 사용하면 단일 파이프라인에서 여러 컨테이너 이미지를 스캔할 수 있습니다. 멀티 컨테이너 스캐닝은 동적 자식 파이프라인을 사용해 스캔을 동시에 실행하므로 전체 파이프라인 실행 시간이 줄어듭니다. 멀티 컨테이너 스캐닝은 다음을 지원합니다:

히스토리

멀티 컨테이너 스캐닝을 사용하면 단일 파이프라인에서 여러 컨테이너 이미지를 스캔할 수 있습니다. 이 기능으로 다음을 수행할 수 있습니다:

  • 여러 이미지를 병렬로 스캔합니다.
  • 단일 구성 파일에서 스캐닝 대상을 구성합니다.
  • 기존 컨테이너 스캐닝 워크플로와 통합합니다.

멀티 컨테이너 스캐닝은 동적 자식 파이프라인을 사용해 스캔을 동시에 실행하므로 전체 파이프라인 실행 시간이 줄어듭니다.

지원되는 이미지#

멀티 컨테이너 스캐닝은 다음을 지원합니다:

  • 공개 레지스트리(Docker Hub, GitLab Container Registry 등)의 이미지
  • 개인 레지스트리(인증이 구성된 경우)의 이미지
  • 멀티 아키텍처 이미지

멀티 컨테이너 스캐닝 켜기#

사전 요구 사항:

  • 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
  • Docker 실행기를 사용하는 GitLab Runner.
  • 리포지터리 루트의 .gitlab-multi-image.yml 구성 파일.
  • 스캔할 컨테이너 이미지 하나 이상.

멀티 컨테이너 스캐닝을 켜려면 다음 단계를 수행합니다:

  1. 리포지터리 루트에 .gitlab-multi-image.yml 파일을 생성합니다:

       scanTargets:
         - name: alpine
           tag: latest
         - name: python
           tag: 3.9-slim
    
  2. .gitlab-ci.yml에 템플릿을 포함합니다:

       include:
         - template: Jobs/Multi-Container-Scanning.latest.gitlab-ci.yml
    
  3. 변경 사항을 커밋하고 푸시합니다. 파이프라인이 자동으로 스캔을 실행합니다.

구성#

.gitlab-multi-image.yml 파일을 편집하여 멀티 컨테이너 스캐닝을 구성합니다.

기본 구성 예시#

scanTargets:
  - name: alpine
    tag: "3.19"
  - name: ubuntu
    tag: "22.04"

전체 구성 예시#

# Include license information in reports
includeLicenses: true

# Configure registry authentication
auths:
  registry.example.com:
    username: ${REGISTRY_USER}
    password: ${REGISTRY_PASSWORD}

# Allow insecure connections (not recommended for production)
allowInsecure: false

# Additional CA certificates for custom registries
additionalCaCertificateBundle: |
  -----BEGIN CERTIFICATE-----
  ...
  -----END CERTIFICATE-----

# Images to scan
scanTargets:
  - name: registry.example.com/myapp
    tag: "v1.2.3"
  - name: postgres
    tag: "15-alpine"

구성 옵션#

Note

멀티 컨테이너 스캐닝에서는 자식 job에 러너 태그를 지정할 수 없지만, 이슈 363687에서 이 동작을 변경할 것을 제안하고 있습니다.

옵션 유형 필수 여부 설명
scanTargets Array Yes 스캔할 컨테이너 이미지 목록
scanTargets[].name String Yes 이미지 이름(선택적 레지스트리 포함)
scanTargets[].tag String No 이미지 태그(기본값: latest)
scanTargets[].registry String No 레지스트리 재정의
includeLicenses Boolean No 보고서에 라이선스 정보 포함
auths Object No 레지스트리 인증 자격 증명
allowInsecure Boolean No 안전하지 않은 HTTPS 연결 허용
additionalCaCertificateBundle String No PEM 형식의 추가 CA 인증서

일반적인 시나리오#

다음 섹션에서는 필요에 맞게 응용할 수 있는 예시 시나리오를 설명합니다.

서로 다른 레지스트리의 이미지 스캔#

scanTargets:
  - name: docker.io/library/nginx
    tag: "1.25"
  - name: registry.gitlab.com/mygroup/myapp
    tag: "main"
  - name: gcr.io/myproject/service
    tag: "prod"

개인 레지스트리 인증 사용#

auths:
  registry.gitlab.com:
    username: ${CI_REGISTRY_USER}
    password: ${CI_REGISTRY_PASSWORD}
  docker.io:
    username: ${DOCKERHUB_USER}
    password: ${DOCKERHUB_TOKEN}

scanTargets:
  - name: registry.gitlab.com/private/image
    tag: latest

컴플라이언스를 위한 특정 버전 스캔#

scanTargets:
  - name: postgres
    tag: "14.10"
  - name: redis
    tag: "7.2.3"
  - name: nginx
    tag: "1.25.3"

동적으로 빌드된 이미지 스캔#

이미지 이름과 태그를 런타임에만 알 수 있는 경우, 정적 .gitlab-multi-image.yml 파일에 scanTargets를 정의할 수 없습니다.

이러한 이미지를 스캔하려면 multi-cs::generate-scan job을 재정의하여, 빌드 job 이 생성한 dotenv 아티팩트로부터 구성 파일을 동적으로 만듭니다:

include:
  - template: Jobs/Multi-Container-Scanning.latest.gitlab-ci.yml

.build-rules: &build-rules
  rules:
    - if: $CONTAINER_SCANNING_DISABLED == 'true' || $CONTAINER_SCANNING_DISABLED == '1'
      when: never
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

build-image-1:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  <<: *build-rules
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
    - export IMAGE1_NAME="$CI_REGISTRY_IMAGE/app1:$CI_COMMIT_SHORT_SHA-$CI_JOB_ID"
    - docker build -f Dockerfiles/Dockerfile.app1 -t "$IMAGE1_NAME" .
    - docker push "$IMAGE1_NAME"
    - echo "IMAGE1_NAME=$IMAGE1_NAME" >> build1.env
  artifacts:
    reports:
      dotenv: build1.env

build-image-2:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  <<: *build-rules
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
    - export IMAGE2_NAME="$CI_REGISTRY_IMAGE/app2:$CI_COMMIT_SHORT_SHA-$CI_JOB_ID"
    - docker build -f Dockerfiles/Dockerfile.app2 -t "$IMAGE2_NAME" .
    - docker push "$IMAGE2_NAME"
    - echo "IMAGE2_NAME=$IMAGE2_NAME" >> build2.env
  artifacts:
    reports:
      dotenv: build2.env

# Override the template job to inject the dynamically generated config
multi-cs::generate-scan:
  needs:
    - job: build-image-1
      artifacts: true
    - job: build-image-2
      artifacts: true
  before_script:
    - !reference [.multi-cs-generate-scan-base, before_script]  # preserve template steps if any
    - IMAGE1_REPO="${IMAGE1_NAME%:*}"
    - IMAGE1_TAG="${IMAGE1_NAME##*:}"
    - IMAGE2_REPO="${IMAGE2_NAME%:*}"
    - IMAGE2_TAG="${IMAGE2_NAME##*:}"
    - |
      cat > .gitlab-multi-image.yml <

CI/CD 변수#

CI/CD 변수를 사용하여 멀티 컨테이너 스캐닝 동작을 사용자 지정할 수 있습니다.

변수 기본값 설명
CONTAINER_SCANNING_DISABLED - 스캐닝을 비활성화하려면 true 또는 1로 설정
AST_ENABLE_MR_PIPELINES true 머지 리퀘스트 파이프라인에서 스캐닝 활성화
CS_SCANNER_IMAGE registry.gitlab.com/.../multiple-container-scanner:0 사용할 스캐너 이미지

멀티 컨테이너 스캐닝 비활성화#

스캐닝을 일시적으로 비활성화하려면 다음을 설정합니다:

variables:
  CONTAINER_SCANNING_DISABLED: "true"

MR 파이프라인 스캐닝 비활성화#

variables:
  AST_ENABLE_MR_PIPELINES: "false"

스캔 결과 보기#

사전 요구 사항:

  • 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
  • 프로젝트에 멀티 컨테이너 스캐닝이 켜져 있어야 합니다.
  • 컨테이너 스캐닝 결과를 포함한 파이프라인이 완료되어 있어야 합니다.

스캔 결과를 보려면 다음 단계를 수행합니다:

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
  2. 머지 리퀘스트 또는 파이프라인 세부 정보 페이지로 이동합니다.
  3. Security 탭을 선택합니다.
  4. 스캔한 모든 이미지에서 감지된 취약점을 확인합니다.

스캔한 이미지마다 다음이 생성됩니다:

  • 컨테이너 스캐닝 보고서.
  • CycloneDX SBOM(소프트웨어 자재 명세서).
  • 라이선스 정보(includeLicenses: true인 경우).

파이프라인 구조#

멀티 컨테이너 스캐닝은 job 두 개를 생성합니다:

  • multi-cs::generate-scan: 스캐닝 구성을 생성합니다
  • multi-cs::trigger-scan: 병렬 스캔 job 이 포함된 자식 파이프라인을 트리거합니다

자식 파이프라인에는 scanTargets의 이미지마다 job 이 하나씩 포함됩니다.

문제 해결#

멀티 컨테이너 스캐닝을 사용할 때 다음 문제가 발생할 수 있습니다.

"configuration file not found" 파이프라인 실패#

원인: .gitlab-multi-image.yml 파일이 없거나 잘못된 위치에 있습니다.

해결 방법: .gitlab-multi-image.yml이 리포지터리 루트에 있는지 확인합니다.

개인 레지스트리 인증 실패#

원인: 잘못된 자격 증명이거나 인증 구성이 누락되었습니다.

해결 방법:

  1. 자격 증명이 올바르고 제대로 구성되어 있는지 확인합니다.

       auths:
         registry.example.com:
           username: ${REGISTRY_USER}
           password: ${REGISTRY_PASSWORD}
    
  2. Settings > CI/CD > Variables에서 변수를 정의합니다.

스캔이 너무 오래 걸림#

원인: 대용량 이미지 여러 개를 순차적으로 스캔하고 있습니다.

해결 방법: 멀티 컨테이너 스캐닝은 이미 스캔을 병렬로 실행합니다.

다음을 고려합니다:

  • 더 작은 기반 이미지 사용
  • 특정 이미지 버전만 스캔
  • GitLab Runner 동시성 설정 조정

자식 파이프라인에 보고서가 표시되지 않음#

원인: 트리거 구성에 strategy: mirror가 없습니다.

해결 방법: 템플릿에는 이 값이 기본적으로 구성되어 있습니다. 템플릿을 사용자 지정했다면 트리거 job에 strategy: mirror가 포함되어 있는지 확인합니다.

자식 파이프라인이 예상과 다른 러너에서 실행됨#

자식 파이프라인 job 이 예상하지 않은 러너에서 실행될 수 있습니다.

이 문제는 자식 파이프라인 job 이 부모 job의 러너 태그를 상속하지 않기 때문에 발생합니다. 이슈 363687에서 이 동작을 변경할 것을 제안하고 있습니다.