Docker 이미지 직접 사용
September 13, 2026 · View on GitHub
평소에는 scan-sbom.sh 스크립트 사용을 권장합니다. 스크립트가 언어 감지와 이미지 선택, 볼륨 마운트를 대신 처리하기 때문입니다. 이 문서는 스크립트를 둘 수 없는 환경(CI 러너, 쿠버네티스 잡 등)에서 이미지를 docker run으로 직접 호출하는 방법을 설명합니다.
이미지와 태그
| 이미지 | 용도 |
|---|---|
ghcr.io/sktelecom/bomlens | 스캔과 후처리 (대표 이름) |
ghcr.io/sktelecom/sbom-generator, ghcr.io/sktelecom/sbom-scanner | 같은 이미지의 별칭 (이전 이름, 같은 다이제스트) |
ghcr.io/sktelecom/bomlens-firmware | 펌웨어 분석용 (GPL 도구 포함, opt-in) (legacy alias: sbom-scanner-firmware) |
ghcr.io/sktelecom/bomlens-deep-cve | 심층 CVE 매칭용 grype 포함 (opt-in). CLI의 --deep-cve와 웹 UI의 심층 CVE 매칭 토글이 쓰며, 둘 다 지금 실행 중인 이미지가 이 이미지가 아니면 곁들임 컨테이너로 자동으로 내려받습니다 |
ghcr.io/sktelecom/bomlens-aibom | AI 모델 ML-BOM 생성용 (opt-in, legacy alias: sbom-scanner-aibom). --model/--model-file과 웹 UI의 AI 모델 타일이 쓰며, 곁들임 컨테이너로 자동으로 내려받습니다 |
latest와 버전 태그를 제공합니다. ghcr.io/sktelecom/bomlens와 bomlens-aibom(및 별칭)은 linux/amd64와 linux/arm64를 모두 지원하고, bomlens-firmware와 bomlens-deep-cve는 linux/amd64만 발행돼 arm64 호스트(Apple Silicon 맥, Arm 서버)에서는 amd64 에뮬레이션 계층 없이 pull이 실패합니다. 이미지는 cosign으로 서명되어 발행됩니다.
docker pull ghcr.io/sktelecom/bomlens:latest
이미지에 들어 있는 것
언어 toolchain이 없는 경량 이미지(python 3.12 slim 기반)입니다. 소스 스캔의 전이 의존성 해석은 스크립트가 cdxgen 언어별 이미지를 따로 받아 처리합니다. 구조는 아키텍처를 참고하세요.
| 도구 | 버전 | 역할 |
|---|---|---|
| syft | v1.51.0 | 이미지, 바이너리, 디렉터리 스캔 |
| Trivy | v0.74.0 | 취약점 보고서 |
| cosign | v3.1.3 | SBOM 서명 |
| jq | — | SBOM 정규화와 고지문 생성 |
| ScanCode Toolkit | 32.5.0 | 정밀 라이선스 탐지 (opt-in 빌드에만 포함) |
| docker CLI | 29.7.2 | 웹 UI가 소스 스캔에서 cdxgen 컨테이너를 sibling으로 띄울 때 사용 |
| cdxgen | 12.8.4 | 모델 계보 정보 보강(bomlens-aibom 이미지 전용) |
도구 버전은 docker/Dockerfile의 ARG로 고정됩니다.
직접 실행
분석 모드는 환경 변수 MODE로 지정합니다. 모든 예시는 산출물을 현재 디렉터리에 남기고 업로드는 하지 않습니다(UPLOAD_ENABLED=false).
Docker 이미지 분석
Windows Git Bash에서는 MSYS가 /var/run/docker.sock과 컨테이너 쪽 경로인
/host-output을 둘 다 Docker에 넘기기 전에 자기 마음대로 Windows 경로로
바꿔버려서 두 마운트가 조용히 깨집니다. 아래 MSYS_NO_PATHCONV와
MSYS2_ARG_CONV_EXCL은 그 변환을 끄고, cygpath -m으로 호스트 쪽 경로만
직접 변환합니다(scripts/scan-sbom.sh도 같은 이유로 같은 조합을 씁니다).
WSL2·macOS·Linux 셸은 경로를 바꾸지 않으므로 그냥 평범한 docker run 줄로
바로 넘어갑니다.
HOSTPATH="$(cygpath -m "$(pwd)" 2>/dev/null || pwd)"
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' docker run --rm \
-v "$HOSTPATH":/host-output \
-v /var/run/docker.sock:/var/run/docker.sock \
-e MODE=IMAGE \
-e TARGET_IMAGE="nginx:alpine" \
-e UPLOAD_ENABLED=false \
-e HOST_OUTPUT_DIR=/host-output \
-e PROJECT_NAME="Nginx" \
-e PROJECT_VERSION="alpine" \
ghcr.io/sktelecom/bomlens:latest
바이너리 파일 분석
HOSTPATH="$(cygpath -m "$(pwd)" 2>/dev/null || pwd)"
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' docker run --rm \
-v "$HOSTPATH":/target \
-v "$HOSTPATH":/host-output \
-e MODE=BINARY \
-e TARGET_FILE=/target/firmware.bin \
-e UPLOAD_ENABLED=false \
-e HOST_OUTPUT_DIR=/host-output \
-e PROJECT_NAME="Firmware" \
-e PROJECT_VERSION="1.0" \
ghcr.io/sktelecom/bomlens:latest
소스 디렉터리 분석
HOSTPATH="$(cygpath -m "$(pwd)" 2>/dev/null || pwd)"
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' docker run --rm \
-v "$HOSTPATH":/src \
-v "$HOSTPATH":/host-output \
-e MODE=SOURCE \
-e UPLOAD_ENABLED=false \
-e HOST_OUTPUT_DIR=/host-output \
-e PROJECT_NAME="MyApp" \
-e PROJECT_VERSION="1.0.0" \
ghcr.io/sktelecom/bomlens:latest
직접 실행의 SOURCE 모드는 컨테이너 안에서 syft가 패키지 매니페스트를 읽는 방식이라 직접 의존성만 잡힐 수 있습니다. 전이 의존성까지 필요하면 cdxgen 언어 이미지를 라우팅하는 scan-sbom.sh를 쓰세요.
고지문과 보고서까지 한 번에
직접 실행에서는 고지문과 보안 보고서가 기본으로 꺼져 있습니다. 다음 변수를 켜면 CLI의 --all과 같은 산출물이 나옵니다.
HOSTPATH="$(cygpath -m "$(pwd)" 2>/dev/null || pwd)"
MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL='*' docker run --rm \
-v "$HOSTPATH":/host-output \
-v /var/run/docker.sock:/var/run/docker.sock \
-e MODE=IMAGE \
-e TARGET_IMAGE="nginx:alpine" \
-e GENERATE_NOTICE=true \
-e GENERATE_SECURITY=true \
-e GENERATE_REPORT=true \
-e UPLOAD_ENABLED=false \
-e HOST_OUTPUT_DIR=/host-output \
-e PROJECT_NAME="Nginx" \
-e PROJECT_VERSION="alpine" \
ghcr.io/sktelecom/bomlens:latest
환경 변수
| 환경 변수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
MODE | X | POSTPROCESS | 분석 모드: SOURCE, IMAGE, BINARY, ROOTFS, FIRMWARE, ANALYZE. 지정하지 않으면 출력 디렉터리에 이미 있는 SBOM을 후처리만 한다 — 실제로 무언가를 스캔하려면 명시적으로 지정해야 한다. |
PROJECT_NAME | O | — | 프로젝트 이름 |
PROJECT_VERSION | O | — | 프로젝트 버전 |
TARGET_IMAGE | 모드별 | — | IMAGE 모드의 이미지명 (docker.sock 마운트 필요) |
TARGET_FILE | 모드별 | — | BINARY/FIRMWARE 모드의 파일 경로 (컨테이너 내부 경로) |
TARGET_DIR | 모드별 | — | ROOTFS 모드의 디렉터리 경로 |
UPLOAD_ENABLED | — | true | false면 업로드 없이 로컬 저장만 (CLI --generate-only와 동일) |
HOST_OUTPUT_DIR | — | — | 산출물을 복사할 마운트 경로 |
GENERATE_NOTICE | — | false | 오픈소스 고지문 생성 (CLI --notice) |
GENERATE_SECURITY | — | false | Trivy 보안 보고서 생성 (CLI --security) |
GENERATE_REPORT | — | false | 오픈소스위험분석보고서 생성 (CLI 기본값과 달리 직접 실행은 꺼짐) |
ENRICH_MAVEN_CPE | — | true | maven 컴포넌트에 groupId로 유도한 NVD 매칭용 cpe:2.3을 부여해 CPE 기반 엔진이 NVD 전용 CVE를 찾게 함. 매핑 불가한 group은 CPE를 붙이지 않음 (AI SBOM은 건너뜀) |
ENRICH_GITHUB_CPE | — | true | 소수의 손검증된 pkg:github/ 컴포넌트(패키지 매니저 생태계가 없는 대형 C/C++ 프로젝트에 흔한, 소스 저장소 좌표로만 식별되는 컴포넌트)에 NVD 매칭용 cpe:2.3을 부여해 CPE 기반 엔진이 NVD 전용 CVE를 찾게 함. 큐레이션 목록에 없으면 CPE를 붙이지 않음 (AI SBOM은 건너뜀) |
ENRICH_INTERPRETER_CPE | — | true | 소수의 손검증된 인터프리터 컴포넌트(예: conda나 NuGet 패키지로 배포된 Python)에 NVD 매칭용 cpe:2.3을 부여해 CPE 기반 엔진이 NVD 전용 CVE를 찾게 함. 큐레이션 목록에 없으면 CPE를 붙이지 않음 (AI SBOM은 건너뜀) |
SECURITY_NVD_VERIFY | — | false | --deep-cve 사용 시: grype nvd:cpe 결과를 실시간 NVD 버전 범위로 검증해 범위 밖 오탐을 제거 (NVD_API_KEY·네트워크 필요, 수 분 추가). 기본 off — 결과는 유지하되 버전 미검증으로 표시 |
NVD_API_KEY | SECURITY_NVD_VERIFY에 필요 | — | deep-cve 버전 필터가 쓰는 NVD API 키. 컨테이너에 이름으로만 전달(값은 인라인하지 않음) |
ENRICH_EOL | — | true | 번들된 오프라인 스냅샷으로 upstream end-of-life가 지난 컴포넌트를 표시 (AI SBOM은 건너뜀) |
ENRICH_MALICIOUS | — | true | 번들된 오프라인 OSV 스냅샷으로 악성 패키지(오타 도용, 계정 탈취 배포본)를 표시. 취약점과 별개 신호이며, 대응도 업그레이드가 아니라 제거와 자격 증명 교체다 |
ENRICH_OS_CONTEXT | — | true | 배포판 패키지 PURL(rpm·deb·apk)에서 operating-system 컴포넌트를 합성. Trivy가 이 컴포넌트를 보고 배포판 취약점 피드를 고르므로, 없으면 공급사 SBOM이나 rootfs 스캔의 OS 패키지는 OS CVE 매칭이 전혀 안 됨. 인식 가능한 배포판 패키지가 없으면 아무 동작도 하지 않음. Trivy가 피드를 제공하지 않는 배포판(예: OpenWRT)도 대상에서 제외 (AI SBOM은 건너뜀) |
STALENESS_ENRICH | — | false | deps.dev 버전 최신성(최신 대비 몇 릴리스 뒤처졌는지) 추가. 네트워크 접근 필요 |
ENRICH_HF_SECURITY | — | true | AIBOM 모드에서 HuggingFace의 파일별 보안 스캔 결과(ClamAV·picklescan)를 ML-BOM에 기록. 메타데이터만 읽고 파일은 내려받지 않음 |
API_KEY, API_URL | 업로드 시 | — | 업로드 자격과 서버 주소. DT는 X-Api-Key, TRUSCA는 Bearer 토큰으로 쓰입니다 |
UPLOAD_TARGET | — | dependency-track | 업로드 대상. dependency-track(DT 호환) 또는 trusca(네이티브 ingest, DT 비호환) |
TRUSCA_PROJECT_ID | trusca일 때 | — | 업로드할 TRUSCA 프로젝트 id(UUID). 사전에 존재해야 합니다(자동 생성 없음) |
TRUSCA_REF | — | main | ingest ref 라벨 |
TRUSCA_RELEASE | — | PROJECT_VERSION | ingest release 라벨 |
BOMLENS_MAVEN_FULL_GRAPH | — | — | Maven 소스 스캔: 1로 설정하면 compile/runtime 스코프로 거르지 않고 전체 해석 그래프를 유지 |
BOMLENS_NODE_FULL_GRAPH | — | — | Node.js 소스 스캔: 1로 설정하면 production 전용 집합 대신 dev와 production을 합친 전체 그래프를 유지 |
BOMLENS_ANDROID_FULL_GRAPH | - | - | Android 소스 스캔(Android SDK 이미지): 1로 설정하면 release 런타임 클래스패스로 거르지 않고 빌드와 테스트 도구까지 포함한 전체 그래프를 유지 |
BOMLENS_KEEP_BUILD_OUTPUT | — | — | 소스 스캔: 1로 설정하면 의존성 해석 결과를 그대로 남김. 기본값에서는 해석 과정이 고쳐 쓴 파일(go.mod, go.sum, Cargo.lock, Gemfile.lock, Package.resolved)을 되돌리고 새로 생긴 빌드 디렉터리를 지워 스캔한 프로젝트를 원래 상태로 돌려줌 |
CYCLONEDX_SPEC_VERSIONS | — | 1.3 1.4 1.5 1.6 | 적합성 검사가 허용하는 CycloneDX spec 버전(공백 구분). 기본 범위를 덮어씀 |
AI_CYCLONEDX_SPEC_VERSIONS | — | 1.3 1.4 1.5 1.6 1.7 | AI SBOM(ML-BOM)이 허용하는 CycloneDX 버전. 1.7을 추가로 허용 |
SPDX_SPEC_VERSIONS | — | SPDX-2.2 SPDX-2.3 | 적합성 검사가 허용하는 SPDX spec 버전 |
PURL_MIN_PCT | — | 90 | 적합성 검사: PURL을 가진 컴포넌트 비율의 최소 기준(필수 검사) |
LICENSE_MIN_PCT | — | 80 | 적합성 검사: 라이선스를 가진 컴포넌트 비율의 최소 기준(권장, 경고만 표시) |
HASH_MIN_PCT | — | 50 | 적합성 검사: 해시를 가진 컴포넌트 비율의 최소 기준(권장, 경고만 표시) |
FIELD_MIN_PCT | — | 80 | 적합성 검사: 규제 대응용 컴포넌트별 필드의 참고 기준 커버리지 |
TRUSCA(구 TrustedOSS Portal)의 네이티브 ingest 엔드포인트(
POST /v1/projects/{id}/sbom-ingest, Bearer 인증)는 Dependency-Track와 호환되지 않습니다. 일반 Dependency-Track 서버로 올릴 때는UPLOAD_TARGET=dependency-track(기본값)을 그대로 두세요.
CLI 플래그와 환경 변수의 전체 대응은 아키텍처의 플래그 매핑을 참고하세요.
이미지 빌드와 배포
이미지를 직접 빌드하거나 멀티 플랫폼으로 발행하는 절차는 기여자용 docker/README에 있습니다.