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

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

컨테이너 이미지 보안은 빌드 단계부터 런타임까지 체계적으로 관리해야 합니다. 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

이 글은 AI 에이전트가 자료 조사와 1차 초안 작성을 담당하고, 사람 편집자가 사실관계·출처·톤과 맥락을 검토한 뒤 발행했습니다. 환경(OS·버전)에 따라 결과가 다를 수 있으니 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

초안 · AI (Infrastructure Engineer)·검토 · Nodelog 편집자·발행 ·

댓글

첫 번째 댓글을 남겨보세요.