멀티 컨테이너 스캐닝
GitLab v19.5Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
요약
멀티 컨테이너 스캐닝을 사용하면 단일 파이프라인에서 여러 컨테이너 이미지를 스캔할 수 있습니다. 멀티 컨테이너 스캐닝은 동적 자식 파이프라인을 사용해 스캔을 동시에 실행하므로 전체 파이프라인 실행 시간이 줄어듭니다. 멀티 컨테이너 스캐닝은 다음을 지원합니다:
멀티 컨테이너 스캐닝을 사용하면 단일 파이프라인에서 여러 컨테이너 이미지를 스캔할 수 있습니다. 이 기능으로 다음을 수행할 수 있습니다:
- 여러 이미지를 병렬로 스캔합니다.
- 단일 구성 파일에서 스캐닝 대상을 구성합니다.
- 기존 컨테이너 스캐닝 워크플로와 통합합니다.
멀티 컨테이너 스캐닝은 동적 자식 파이프라인을 사용해 스캔을 동시에 실행하므로 전체 파이프라인 실행 시간이 줄어듭니다.
지원되는 이미지#
멀티 컨테이너 스캐닝은 다음을 지원합니다:
- 공개 레지스트리(Docker Hub, GitLab Container Registry 등)의 이미지
- 개인 레지스트리(인증이 구성된 경우)의 이미지
- 멀티 아키텍처 이미지
멀티 컨테이너 스캐닝 켜기#
사전 요구 사항:
- 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
- Docker 실행기를 사용하는 GitLab Runner.
- 리포지터리 루트의
.gitlab-multi-image.yml구성 파일. - 스캔할 컨테이너 이미지 하나 이상.
멀티 컨테이너 스캐닝을 켜려면 다음 단계를 수행합니다:
-
리포지터리 루트에
.gitlab-multi-image.yml파일을 생성합니다:scanTargets: - name: alpine tag: latest - name: python tag: 3.9-slim -
.gitlab-ci.yml에 템플릿을 포함합니다:include: - template: Jobs/Multi-Container-Scanning.latest.gitlab-ci.yml -
변경 사항을 커밋하고 푸시합니다. 파이프라인이 자동으로 스캔을 실행합니다.
구성#
.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"
구성 옵션#
멀티 컨테이너 스캐닝에서는 자식 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 권한.
- 프로젝트에 멀티 컨테이너 스캐닝이 켜져 있어야 합니다.
- 컨테이너 스캐닝 결과를 포함한 파이프라인이 완료되어 있어야 합니다.
스캔 결과를 보려면 다음 단계를 수행합니다:
- 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 머지 리퀘스트 또는 파이프라인 세부 정보 페이지로 이동합니다.
- Security 탭을 선택합니다.
- 스캔한 모든 이미지에서 감지된 취약점을 확인합니다.
스캔한 이미지마다 다음이 생성됩니다:
- 컨테이너 스캐닝 보고서.
- 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이 리포지터리 루트에 있는지 확인합니다.
개인 레지스트리 인증 실패#
원인: 잘못된 자격 증명이거나 인증 구성이 누락되었습니다.
해결 방법:
-
자격 증명이 올바르고 제대로 구성되어 있는지 확인합니다.
auths: registry.example.com: username: ${REGISTRY_USER} password: ${REGISTRY_PASSWORD} -
Settings > CI/CD > Variables에서 변수를 정의합니다.
스캔이 너무 오래 걸림#
원인: 대용량 이미지 여러 개를 순차적으로 스캔하고 있습니다.
해결 방법: 멀티 컨테이너 스캐닝은 이미 스캔을 병렬로 실행합니다.
다음을 고려합니다:
- 더 작은 기반 이미지 사용
- 특정 이미지 버전만 스캔
- GitLab Runner 동시성 설정 조정
자식 파이프라인에 보고서가 표시되지 않음#
원인: 트리거 구성에 strategy: mirror가 없습니다.
해결 방법: 템플릿에는 이 값이 기본적으로 구성되어 있습니다. 템플릿을 사용자 지정했다면
트리거 job에 strategy: mirror가 포함되어 있는지 확인합니다.
자식 파이프라인이 예상과 다른 러너에서 실행됨#
자식 파이프라인 job 이 예상하지 않은 러너에서 실행될 수 있습니다.
이 문제는 자식 파이프라인 job 이 부모 job의 러너 태그를 상속하지 않기 때문에 발생합니다. 이슈 363687에서 이 동작을 변경할 것을 제안하고 있습니다.