/인프라/컨테이너 이미지 보안: 빌드부터 런타임까지 완전 강화 가이드
Infrastructure컨테이너보안Docker

컨테이너 이미지 보안: 빌드부터 런타임까지 완전 강화 가이드

This article is not yet available in English. Showing the original Korean version.

컨테이너 이미지 보안은 빌드 단계부터 런타임까지 체계적으로 관리해야 합니다. Docker 이미지 취약점 스캐닝, SBOM 생성, 런타임 보안 정책까지 실전 가이드를 제공합니다.

컨테이너 이미지 보안: 빌드부터 런타임까지 완전 강화 가이드

왜 컨테이너 이미지 보안이 중요한가

컨테이너 기반 인프라가 일반화되면서 이미지 보안은 현대 DevSecOps의 핵심 과제가 됐습니다. 2024년 Sysdig 보고서에 따르면 프로덕션 컨테이너의 87%가 심각(High) 이상의 취약점을 포함하고 있으며, 이 중 다수는 단순한 베이스 이미지 업데이트로 해결할 수 있는 것들입니다.

공격 표면은 크게 세 가지로 나뉩니다:

  • 빌드 시: 취약한 베이스 이미지, 불필요한 패키지, 하드코딩된 시크릿
  • 레지스트리: 서명되지 않은 이미지, 접근 제어 미비
  • 런타임: 과도한 권한, 민감한 마운트, 비정상 프로세스 실행

빌드 단계 보안 강화

1. 최소화된 베이스 이미지 사용

Dockerfile
# 나쁜 예 — 불필요한 패키지 포함
FROM ubuntu:22.04

# 좋은 예 — distroless로 최소화
FROM gcr.io/distroless/nodejs20-debian12

# 또는 Alpine 기반
FROM node:20-alpine3.19

Alpine은 5MB 수준으로 공격 표면을 대폭 줄이고, distroless는 셸조차 없어 컨테이너 탈출 시 공격자가 할 수 있는 일을 최소화합니다.

2. 멀티스테이지 빌드

Dockerfile
# 빌드 스테이지
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# 프로덕션 스테이지 — 빌드 도구 제외
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER nonroot
EXPOSE 3000
CMD ["dist/server.js"]

3. 루트 사용자 금지

Dockerfile
# 전용 비권한 사용자 생성
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

Kubernetes에서는 PodSecurityContext로 이를 강제할 수 있습니다:

YAML
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false

취약점 스캐닝: Trivy 실전 활용

Trivy는 현재 가장 널리 쓰이는 오픈소스 컨테이너 스캐너입니다.

기본 스캔

Bash
# 이미지 스캔
trivy image nginx:1.25

# 심각도 필터링 (HIGH, CRITICAL만)
trivy image --severity HIGH,CRITICAL nginx:1.25

# JSON 출력 (CI 파이프라인용)
trivy image --format json --output results.json myapp:latest

# 특정 CVE 무시 (false positive 처리)
trivy image --ignorefile .trivyignore myapp:latest

CI/CD 통합 (GitHub Actions)

YAML
- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: ${{ env.IMAGE_TAG }}
    format: sarif
    output: trivy-results.sarif
    severity: CRITICAL,HIGH
    exit-code: 1  # 취약점 발견 시 빌드 실패

- name: Upload Trivy scan results
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: trivy-results.sarif

SBOM 생성

SBOM(Software Bill of Materials)은 이미지에 포함된 모든 컴포넌트를 목록화합니다:

Bash
# CycloneDX 형식으로 SBOM 생성
trivy image --format cyclonedx --output sbom.json myapp:latest

# SPDX 형식
trivy image --format spdx-json --output sbom.spdx.json myapp:latest

이미지 서명: Cosign + Sigstore

Bash
# Cosign 설치 및 키 생성
cosign generate-key-pair

# 이미지 서명
cosign sign --key cosign.key registry.example.com/myapp:latest

# 서명 검증
cosign verify --key cosign.pub registry.example.com/myapp:latest

# keyless 서명 (OIDC 기반, GitHub Actions)
cosign sign --yes registry.example.com/myapp:${{ github.sha }}

Kubernetes에서 서명된 이미지만 허용하려면 Kyverno나 OPA Gatekeeper 정책을 사용합니다:

YAML
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-image
    match:
      any:
      - resources:
          kinds: [Pod]
    verifyImages:
    - imageReferences: ["registry.example.com/*"]
      attestors:
      - count: 1
        entries:
        - keys:
            publicKeys: |- 
              -----BEGIN PUBLIC KEY-----
              ...

런타임 보안: Falco

Falco는 컨테이너 런타임에서 비정상 행위를 실시간 탐지합니다.

YAML
# falco-rules.yaml — 주요 탐지 규칙 예시
- rule: Terminal shell in container
  desc: 컨테이너 내 셸 실행 탐지
  condition: >
    spawned_process and container and
    proc.name in (shell_binaries)
  output: >
    Shell spawned in container (user=%user.name container=%container.name
    image=%container.image.repository)
  priority: WARNING

- rule: Write below etc
  desc: /etc 디렉토리 쓰기 시도
  condition: >
    open_write and container and fd.directory=/etc
  output: File opened for writing below /etc (user=%user.name file=%fd.name)
  priority: ERROR

레지스트리 보안 체크리스트

항목권장 설정
접근 제어RBAC + 최소 권한 원칙
이미지 스캔푸시 시 자동 스캔 활성화
서명 정책서명된 이미지만 pull 허용
취약 이미지CRITICAL 발견 시 자동 격리
감사 로깅모든 pull/push 이벤트 기록
보존 정책오래된 이미지 자동 삭제

보안 강화 로드맵

  1. 즉시 적용 (1주): Trivy를 CI 파이프라인에 통합, CRITICAL 취약점 빌드 차단
  2. 단기 (1달): 멀티스테이지 빌드 + distroless/Alpine 마이그레이션, non-root 사용자 강제
  3. 중기 (3달): Cosign 이미지 서명 도입, Kyverno 서명 검증 정책 적용
  4. 장기 (6달): Falco 런타임 탐지, SBOM 자동 생성 및 취약점 추적 체계 완성

이미지 보안은 한 번 설정하고 끝나는 게 아닙니다. 새로운 CVE가 매일 발표되므로, 배포된 이미지를 주기적으로 재스캔하고 베이스 이미지를 최신으로 유지하는 자동화 체계를 구축하는 것이 핵심입니다.

취약점 스캔 결과 대응 의사결정표

Trivy가 수백 건을 쏟아낼 때, 전부 고치려다 아무것도 못 고치는 것이 최악입니다.

상황판단조치
Critical + 수정 버전 존재즉시 대응베이스 이미지/패키지 버전 업 → 재빌드·재배포
Critical인데 패치 미출시노출면 평가해당 라이브러리가 실제 실행 경로에 있는지 확인 — 미사용이면 예외 등록(만료일 필수), 사용 중이면 완화책(네트워크 격리 등) 문서화
취약점 대부분이 베이스 이미지 유래구조 개선distroless/alpine 등 최소 이미지로 교체가 개별 패치보다 효과적
동일 CVE가 매주 재등장프로세스 문제베이스 이미지 주기적 리빌드 파이프라인(주 1회) 부재 — 자동화
오탐 판단근거 기록.trivyignore에 사유·검토자·만료일 주석과 함께 등록

운영 체크리스트

  • CI 게이트 기준 명문화 — 예: Critical=차단, High=경고 후 7일 내 조치
  • 예외(ignore) 목록에 만료일 — 영구 예외 금지
  • 런타임 이미지와 스캔 이미지의 태그 일치 검증 (latest 스캔은 무의미)
  • 서명 검증을 배포 어드미션에서 강제해야 서명이 의미를 가짐

자주 묻는 질문 (FAQ)

Q. 컨테이너 이미지 보안 검증은 어떻게 하나요? A. ① 취약점 스캔 — Trivy·Grype로 OS·라이브러리 CVE 검사 ② 이미지 서명 검증 — Cosign으로 서명·검증해 변조 방지 ③ SBOM 생성 — 구성요소 목록화 ④ 베이스 이미지 최소화(distroless·slim)로 공격면 축소. CI 파이프라인에서 스캔을 게이트로 걸어 실패 시 배포를 막는 것이 핵심입니다.

Q. 이미지 스캔은 언제 하나요? A. 빌드 시(CI), 레지스트리 등록 후, 런타임(주기적 재스캔) 3단계 모두 권장합니다. CVE는 배포 이후에도 새로 공개되므로 이미 떠 있는 이미지도 주기적으로 재검증해야 합니다.

✦ ✦ ✦
편집 검토 · Editorial Review

Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

편집 책임 · Nodelog 기술 편집팀·발행 ·

Comments

Be the first to comment.