개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Docker 보안 — 컨테이너 보안 체크리스트

2025년 7월 12일
Docker보안root 사용자read-only최소 이미지

컨테이너는 격리된 환경처럼 보이지만, 잘못 설정하면 호스트 시스템 전체가 위협에 노출된다. 개발 환경에서 동작하던 이미지를 그대로 프로덕션에 올리는 순간, 보안 구멍이 함께 배포된다. 아래 다섯 가지 원칙만 지켜도 공격 표면을 크게 줄일 수 있다.

non-root 사용자 실행

컨테이너 내부 프로세스가 root(UID 0) 로 실행되면, 컨테이너 탈출 취약점이 발생했을 때 호스트의 root 권한과 동일하게 작동한다.

FROM node:20-alpine

# 전용 사용자 생성
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app
COPY --chown=appuser:appgroup . .

USER appuser

CMD ["node", "server.js"]

USER 지시어로 비특권 사용자를 지정하면, 프로세스가 얻을 수 있는 권한이 해당 UID로 제한된다.

UID 0 — Linux에서 root 계정의 사용자 ID. 컨테이너 내부와 호스트 커널이 같은 UID 네임스페이스를 공유하므로 탈출 시 호스트 root와 동일한 권한을 갖는다.

Read-only 파일시스템

런타임에 파일시스템을 수정할 필요가 없는 서비스라면 read-only 모드로 실행해 악성 파일 드롭을 차단한다.

docker run --read-only \
  --tmpfs /tmp \
  --tmpfs /var/run \
  my-app:latest

--tmpfs 로 쓰기가 필요한 경로만 메모리 기반 임시 파일시스템으로 마운트한다.

최소 기반 이미지 (alpine / distroless)

이미지에 포함된 패키지가 많을수록 취약점 공격 면적이 넓어진다.

기반 이미지압축 크기쉘 포함권장 용도
ubuntu:22.04~29MBO디버깅, 범용
node:20-alpine~7MBO (ash)Node.js 서비스
gcr.io/distroless/nodejs20~4MBX프로덕션 Node.js
scratch0MBX정적 바이너리

Alpine 은 musl libc 기반으로 크기가 작고, distroless 는 패키지 매니저와 쉘 자체가 없어 쉘 인젝션 공격 경로를 원천 차단한다.

distroless — Google이 관리하는 이미지 시리즈. OS 패키지와 쉘을 제거하고 런타임 라이브러리만 포함해 공격 표면을 최소화한다.

시크릿 관리

환경 변수나 이미지 레이어에 시크릿을 하드코딩하면 docker history 만으로 노출된다.

[빌드 단계]          [런타임]
Dockerfile           Docker Secret / Vault
     |                      |
     v                      v
  이미지 레이어  ←X— API_KEY 절대 포함 금지
                       |
                  /run/secrets/api_key  (tmpfs, 컨테이너만 접근)
# docker-compose.yml
services:
  api:
    image: my-app:latest
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

Docker Swarm의 Secret 또는 HashiCorp Vault 를 통해 런타임에만 파일로 마운트하고, 이미지 레이어에는 흔적을 남기지 않는다.

이미지 취약점 스캔

배포 전 Trivy 또는 Docker Scout 로 CVE를 자동 검출한다.

# Trivy 스캔
trivy image --severity HIGH,CRITICAL my-app:latest

# Docker Scout
docker scout cves my-app:latest

CI 파이프라인에 스캔 단계를 추가해 HIGH 이상 취약점이 발견되면 빌드를 실패시키는 것이 권장 패턴이다.

CI Pipeline
  build → scan (trivy) → push → deploy
              |
         HIGH CVE 발견
              |
           빌드 실패 → 슬랙 알림

CVE — Common Vulnerabilities and Exposures. 공개된 보안 취약점에 부여되는 고유 식별자(예: CVE-2024-12345).

다섯 가지 체크리스트를 모두 통과한 이미지가 최소한의 보안 기준을 충족한다고 볼 수 있다. non-root, read-only, 최소 이미지, 시크릿 분리, 취약점 스캔 — 이 순서대로 Dockerfile과 배포 설정을 점검하라.

← 이전 글Multi-stage Build — 이미지 크기를 줄이는 빌드 최적화
다음 글 →Docker 이미지 최적화 — 빌드 캐시와 레이어 최소화