Trivy 설치·사용법, Grype/Snyk 비교, GitHub Actions CI/CD 통합, Dockerfile 보안 베스트 프랙티스, 취약점 우선순위 판단.
한 줄 요약: 컨테이너 이미지 보안 스캐닝은 배포 전 알려진 CVE와 잘못된 설정을 자동으로 탐지하는 필수 DevSecOps 단계다. Trivy 한 줄 명령으로 시작할 수 있다.
이 글이 필요한 사람:
Docker 이미지를 프로덕션에 배포하는 백엔드/DevOps 엔지니어
CI/CD 파이프라인에 보안 검사를 추가하려는 팀
컨테이너 보안 도구를 비교하고 선택해야 하는 시큐리티 담당자
Trivy, Grype, Snyk 중 어떤 도구를 쓸지 결정하지 못한 개발자
왜 컨테이너 이미지 보안 스캐닝이 필요한가
컨테이너 이미지는 OS 라이브러리, 런타임, 애플리케이션 의존성을 한 레이어에 묶는다. node:18-alpine 같은 공식 베이스 이미지도 알려진 CVE를 포함할 수 있다. 2023년 Sysdig 보고서에 따르면 퍼블릭 컨테이너 이미지의 87%가 고위험 이상 취약점을 포함하고 있었다.
문제는 빌드 시점이 아니라 운영 시점에 취약점이 알려진다는 점이다. 6개월 전에 빌드한 이미지가 오늘 기준 CRITICAL 취약점을 가질 수 있다. 스캐닝 없이 배포하면 공격 표면을 그대로 열어두는 것과 같다.
공급망 공격 방어: 베이스 이미지나 패키지 레지스트리가 악성 코드를 포함할 경우 조기 탐지
규정 준수: SOC 2, ISO 27001, PCI-DSS 등에서 취약점 관리 프로세스를 요구
비용 절감: 운영 중 패치보다 빌드 파이프라인에서 차단하는 것이 훨씬 저렴
컨테이너 이미지 보안 스캐닝 실전 가이드 — Trivy, Grype, CI/CD 통합 — 보안 아키텍처 다이어그램 (출처: 공식 문서 및 벤치마크 데이터 기반)
Trivy 설치 및 기본 사용법
Trivy는 Aqua Security가 개발한 오픈소스 취약점 스캐너다. 컨테이너 이미지, 파일시스템, Git 저장소, IaC(Terraform, Helm) 등을 스캔할 수 있다. 설치가 단순하고 별도 데몬이 필요 없어 CI/CD 통합이 쉽다.
Trivy 설치 (macOS / Linux / Docker)
# macOS (Homebrew)
brew install trivy
# Linux (apt)
sudo apt-get install wget apt-transport-https gnupg lsb-release
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy
# Docker로 실행 (설치 없이)
docker run --rm aquasec/trivy image nginx:latest
설치 후 이미지를 스캔하는 기본 명령은 다음과 같다. --severity로 출력할 취약점 등급을 필터링하고, --exit-code 1을 지정하면 CRITICAL 취약점 발견 시 CI를 실패시킬 수 있다.
컨테이너 이미지 보안 스캐닝 실전 가이드 — Trivy, Grype, CI/CD 통합 — 위협 모델 시각화 (출처: 공식 문서 및 벤치마크 데이터 기반)
VEX (Vulnerability Exploitability eXchange) 지원: Trivy 0.46+에서 VEX 문서를 지원한다. 공급업체가 "이 취약점은 우리 제품에서 실제로 악용 불가"라고 명시한 경우 스캔 결과에서 제외할 수 있어 오탐 노이즈를 줄일 수 있다.
Grype / Snyk 등 대안 도구 비교
Trivy만이 선택지가 아니다. 팀 규모, 예산, 스택에 따라 다른 도구가 더 적합할 수 있다.
Grype는 Anchore가 만든 경량 스캐너로, Syft로 SBOM을 먼저 생성한 다음 Grype로 취약점을 매핑하는 패턴을 권장한다. SBOM을 아티팩트로 저장해두면 나중에 새로운 CVE가 공개됐을 때 이미지를 다시 빌드하지 않고도 기존 SBOM에 재스캔이 가능하다.
Grype 사용 예시 (Syft SBOM 조합)
# Grype 설치
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# 직접 이미지 스캔
grype nginx:latest
# Syft로 SBOM 생성 후 Grype 스캔
syft nginx:latest -o spdx-json > sbom.spdx.json
grype sbom:./sbom.spdx.json
CI/CD 파이프라인 통합 — GitHub Actions 예시
보안 스캐닝을 CI 파이프라인에 넣으면 취약 이미지가 레지스트리에 푸시되기 전에 차단된다. 아래는 docker build → trivy scan → push 순서로 구성한 GitHub Actions 워크플로우다.
컨테이너 이미지 보안 스캐닝 실전 가이드 — Trivy, Grype, CI/CD 통합 — 취약점 분석 플로우차트 (출처: 공식 문서 및 벤치마크 데이터 기반)
format: sarif로 출력하면 GitHub Security 탭에서 취약점을 코드 리뷰 형태로 확인할 수 있다. SARIF 업로드는 if: always()로 설정해 스캔 실패 시에도 결과를 확인할 수 있게 한다.
정책 분리 팁: PR 단계에서는 exit-code: 0으로 경고만 하고, main 브랜치 머지 시에는 exit-code: 1로 차단하는 정책을 쓰면 개발 속도와 보안을 균형 있게 유지할 수 있다.
Dockerfile 베스트 프랙티스 — 취약점 최소화
스캐닝은 사후 탐지다. 이미지를 처음부터 작게, 권한 없이 만드는 것이 선제 방어다. 핵심 패턴 두 가지를 짚는다.
1. 멀티스테이지 빌드로 최종 이미지 크기 줄이기
빌드 도구(컴파일러, devDependencies)는 최종 이미지에 포함할 필요가 없다. 멀티스테이지 빌드로 런타임에 필요한 파일만 복사하면 공격 표면이 줄어든다.
멀티스테이지 빌드 예시 (Node.js)
# 빌드 스테이지
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 런타임 스테이지 — 빌드 도구 제외
FROM node:20-alpine AS runtime
WORKDIR /app
# 비root 사용자 생성 및 적용
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
USER appuser
EXPOSE 3000
CMD ["node", "dist/index.js"]
비root 실행의 중요성: 컨테이너가 root로 실행되면 컨테이너 탈출(container escape) 취약점 악용 시 호스트 시스템 전체가 위험에 노출된다. USER 인스트럭션으로 반드시 비root 사용자로 전환하라.
2. 베이스 이미지 선택 기준
alpine 계열: 패키지 수가 적어 취약점이 적다. 단, glibc 대신 musl을 사용하므로 일부 바이너리와 호환 문제가 있을 수 있다.
distroless: Google이 제공하는 OS 패키지 없는 이미지. 쉘 자체가 없어 공격자가 exec로 진입할 수 없다. Java, Python, Node 등 지원.
Chainguard Images: 서명된 이미지, 최소 패키지, 매일 리빌드. CVE 0건을 목표로 운영된다.
컨테이너 이미지 보안 스캐닝 실전 가이드 — Trivy, Grype, CI/CD 통합 — 보안 레이어 구성도 (출처: 공식 문서 및 벤치마크 데이터 기반)
취약점 우선순위 판단 기준
Trivy가 보고하는 수십 개 취약점을 모두 즉시 패치할 수는 없다. 실무에서 쓸 수 있는 우선순위 판단 기준을 정리한다.
취약점 관리는 한 번에 끝나지 않는다. 스캐닝을 파이프라인에 고정하고, 주기적으로 이미지를 리빌드(베이스 이미지 업데이트)하며, .trivyignore에 수용 근거를 주석으로 남기는 것이 지속 운영의 기본이다.