컨테이너 이미지 리빌드 없이 CVE 패치하기 — CNCF Copa(Copacetic) 실전 후기

이군·2026년 7월 11일

컨테이너 이미지를 취약점 스캐너로 돌려본 적이 있다면 누구나 한 번쯤 겪는 상황이 있습니다. 스캔 결과에 수천 건의 CVE가 쏟아지는데, 정작 애플리케이션 코드는 아무 문제가 없고 대부분이 베이스 이미지의 OS 패키지에서 나온 것들입니다. 베이스 이미지가 새로 릴리스되기를 기다리거나, Dockerfile을 열어 apt-get upgrade를 끼워 넣고 전체 리빌드·재테스트를 돌리는 것이 지금까지의 대응이었습니다.

Copa(Copacetic)는 이 문제를 다르게 풉니다. 이미지를 리빌드하지 않고, 취약한 OS 패키지만 업데이트한 레이어 하나를 기존 이미지 위에 얹습니다. Microsoft가 시작해 현재 CNCF 샌드박스 프로젝트로 관리되고 있으며, 내부적으로 BuildKit을 사용합니다.

이 글에서는 Copa를 소개만 하고 끝내는 대신, Node 18 이미지(Ubuntu 22.04 기반)를 대상으로 실제 패치를 돌려 전/후 CVE 수치를 비교한 결과를 공유합니다.

Copa의 동작 방식

Copa의 워크플로는 단순합니다.

  1. 스캔 — Trivy로 이미지를 스캔해 JSON 리포트를 만듭니다.
  2. 패치 — Copa가 리포트를 읽고, 수정 버전이 존재하는 OS 패키지를 배포판 저장소에서 받아 업그레이드한 패치 레이어를 생성합니다. 이 작업은 BuildKit 위에서 수행됩니다.
  3. 재스캔 — 패치된 이미지를 다시 스캔해 결과를 확인합니다.

핵심은 Dockerfile도, 소스 코드도, CI 파이프라인 전체 리빌드도 필요 없다는 점입니다. 원본 이미지의 기존 레이어는 그대로 유지되고, 맨 위에 업데이트 레이어 하나만 추가됩니다.

실험 환경

항목내용
대상 이미지cimg/node:18.20.4 (Node.js 18, Ubuntu 22.04 기반)
스캐너Trivy (최신 이미지, --scanners vuln)
패처Copa v0.14.2
빌드 백엔드moby/buildkit 컨테이너 (docker-container://buildkitd)

실행한 명령은 다음이 전부입니다.

# 1) 베이스라인 스캔 (Copa 입력용 JSON 리포트)
trivy image --scanners vuln -f json -o node18-before.json cimg/node:18.20.4

# 2) BuildKit 데몬 기동
docker run -d --rm --privileged --name buildkitd \
  --entrypoint buildkitd moby/buildkit:latest

# 3) Copa 패치 실행
copa patch -i cimg/node:18.20.4 -r node18-before.json \
  -t 18.20.4-patched -a docker-container://buildkitd --timeout 30m

# 4) 패치된 이미지 재스캔
trivy image --scanners vuln -f json -o node18-after.json cimg/node:18.20.4-patched

결과: OS 패키지 CVE 60% 감소, 수정판 존재분은 100% 제거

Copa 실행은 약 1분 30초 만에 끝났고, 148개의 보안 업데이트가 설치됐습니다. Copa가 출력한 요약은 다음과 같습니다.

Patch Summary: 6772 total, 4067 patched, 2705 skipped
Patched image (linux/amd64): cimg/node:18.20.4-patched

Trivy 재스캔 결과도 이 숫자와 정확히 일치했습니다.

OS 패키지 CVE (심각도별)

심각도패치 전패치 후감소
CRITICAL217-14 (-67%)
HIGH388170-218 (-56%)
MEDIUM5,6102,190-3,420 (-61%)
LOW753338-415 (-55%)
합계6,7722,705-4,067 (-60%)

주목할 점은 감소량 4,067건이 우연이 아니라는 것입니다. 패치 전 리포트에서 FixedVersion(수정 버전)이 존재하는 CVE가 정확히 4,067건이었고, Copa는 그 전부를 패치했습니다. 즉:

배포판 저장소에 수정판이 올라와 있는 CVE는 100% 제거됐고, 남은 2,705건은 전부 아직 수정판이 출시되지 않은(no fixed version) CVE입니다.

이것이 Copa의 성격을 가장 잘 보여줍니다. Copa는 마법을 부리는 도구가 아니라, "패키지 매니저로 올릴 수 있는 것을 전부, 리빌드 없이, 빠르게" 올려 주는 도구입니다.

패치 후 이미지는 정상 동작하는가

패치 레이어가 런타임을 깨뜨리지 않는지도 확인했습니다.

$ docker run --rm cimg/node:18.20.4-patched node --version
v18.20.4

애플리케이션 바이너리와 기존 레이어는 건드리지 않으므로, 태그 교체만으로 배포 파이프라인에 태울 수 있습니다.

알아두면 좋은 제약 사항

실험에서 그대로 드러난, Copa 도입 전에 알아야 할 특성들입니다.

  • OS 패키지 전용입니다. 이미지 안의 npm 패키지, Go 바이너리 등 언어 레벨 취약점(이번 실험에서 991건)은 패치 전후 그대로였습니다. node_modules나 런타임 자체의 취약점은 여전히 애플리케이션 빌드 단계에서 관리해야 합니다.
  • 수정판이 없는 CVE는 남습니다. 배포판이 fix를 내지 않은 취약점은 Copa가 해결할 수 없습니다. 이 잔여분은 VEX 문서나 스캐너의 --ignore-unfixed 옵션으로 노이즈를 관리하는 것이 현실적입니다. 참고로 Copa는 패치 결과를 OpenVEX 형식으로 출력하는 기능(-f openvex -o report.vex)도 제공합니다.
  • 이미지 크기가 늘어납니다. 업데이트 레이어가 추가되므로 크기가 증가합니다(이번 실험에서는 무압축 내보내기 기준 1.92GB → 2.87GB). --compression gzip 같은 압축 옵션으로 상당 부분 줄일 수 있습니다.
  • 네트워크로 배포판 저장소에 접근할 수 있어야 합니다. 패치 과정에서 대상 이미지의 패키지 저장소(Ubuntu라면 archive.ubuntu.com, security.ubuntu.com)에서 실제 패키지를 내려받습니다. 폐쇄망이라면 내부 미러가 필요합니다.

어디에 쓰면 좋은가

  • 베이스 이미지 릴리스와 보안 대응의 시차 메우기 — 업스트림 이미지가 새로 나올 때까지 기다리지 않고 즉시 대응할 수 있습니다.
  • EOL·레거시 이미지의 수명 연장 — 리빌드 체계가 사라진 오래된 이미지도, 저장소에 남아 있는 fix까지는 끌어올릴 수 있습니다.
  • 레지스트리 단위 일괄 패치 — 스캔 → 패치 → 재스캔이 전부 CLI라서 CI/CD나 크론으로 자동화하기 쉽습니다. Copa는 GitHub Action도 제공합니다.

마치며

"이미지 CVE가 수천 건"이라는 스캔 결과 앞에서 할 수 있는 일이 리빌드뿐이라면 대응은 늘 느려집니다. 이번 실측에서 Copa는 리빌드 없이 1분 30초 만에 OS 패키지 CVE의 60%(CRITICAL은 67%)를 제거했고, 수정판이 존재하는 취약점 기준으로는 빠짐없이 전부 패치했습니다. 스캐너 리포트를 입력으로 받아 패키지 매니저가 할 수 있는 일을 자동화해 주는, 역할이 명확하고 예측 가능한 도구입니다. 이미지 취약점 대응 파이프라인에 넣을 도구를 찾고 있다면 한번 돌려볼 가치가 충분합니다.

참고 링크

profile
이군의 보안, 그리고 생각을 다룹니다.

0개의 댓글