1P by GN⁺ | ★ favorite | 댓글과 토론
  • 컨테이너 레지스트리는 겉보기엔 단순하지만, 잘못된 태그, 플랫폼 불일치, 레이어 누락, 실제 삭제 실패 같은 문제를 디버깅하려면 내부 동작 원리를 반드시 이해해야 함
  • 레지스트리의 핵심은 콘텐츠 주소 지정 방식(content-addressable) blob 저장소로, 모든 레이어·설정 파일·아티팩트는 digest를 주소로 삼아 저장됨
  • 이미지 push는 blob 업로드 후 manifest로 묶는 순서로 진행되고, pull은 manifest를 먼저 받아 blob을 순차적으로 내려받는 역순 구조임
  • 이미지 삭제는 단순 언태그만으로는 완전 제거가 되지 않으며, 다른 manifest에서 공유 중인 레이어를 먼저 확인한 뒤 blob까지 직접 삭제해야 함
  • 멀티 플랫폼 이미지는 기존 API 엔드포인트를 그대로 유지하면서 image index(manifest list)라는 추가 간접 계층 하나만 도입해 구현됨

Registry API 개요

  • 현대 컨테이너 레지스트리 대부분은 OCI Distribution Specification을 구현하며, 이 스펙은 콘텐츠 배포를 표준화하는 API 프로토콜을 정의함
  • Registry API는 실제로 간결하고 이해하기 쉬우며, curl만으로도 충분히 직접 조작 가능

Blob 업로드 및 다운로드

  • 레지스트리는 본질적으로 콘텐츠 주소 지정 blob 저장소로, 파일을 로컬에서 해싱한 뒤 digest를 주소로 사용해 업로드함
  • 가장 단순한 업로드 방식은 Monolithic PUT 방식으로, POST로 세션을 초기화한 뒤 PUT으로 blob을 전송하는 2단계 구조
    • 대용량 파일에는 POST + PATCH + PUT 청크 업로드 방식이 더 효율적이나, 소형 blob의 경우 Monolithic PUT으로 충분
  • 업로드 성공 시 HTTP/2 201 Created 응답과 함께 새 blob의 위치를 가리키는 Location 헤더가 반환됨
  • 다운로드는 digest만 알면 GET /v2/<repo>/blobs/<digest>로 바로 수행 가능

이미지 Push

  • 이미지 push 절차: (1) 각 rootfs 레이어 blob 업로드 → (2) image configuration blob 업로드 → (3) 모든 digest를 하나의 JSON 문서로 묶는 manifest 파일 push
  • manifest는 PUT /v2/<repo>/manifests/<tag> 엔드포인트로 업로드하며, 이 시점에 태그가 생성됨
  • 실제 클라이언트(예: docker push)는 blob 업로드를 병렬로 수행하나, 원리 이해를 위해 순차 처리도 가능
  • 이미지 디렉터리 구성 예시: config.json, layer-1.tar.gz, layer-2.tar.gz, manifest.json

태그 목록 조회

  • GET /v2/<repo>/tags/list 엔드포인트로 특정 레포지터리의 모든 태그 목록 조회 가능
  • 이 기능은 docker CLI에서는 노출되지 않으며, curl 또는 crane, regctl 같은 도구로만 접근 가능
    • crane, regctl은 동일 엔드포인트를 ls 명령으로 래핑한 것

이미지 Pull

  • pull 절차는 push의 역순: (1) GET /v2/<repo>/manifests/<tag>manifest 조회 → (2) manifest에 명시된 digest로 모든 blob 다운로드
  • 현대 manifest는 rootfs 레이어·이미지 설정 외에도 Helm 차트, SBOM, 출처 증명(provenance attestation), LLM 가중치 등 임의 아티팩트를 blob으로 참조하는 범용 저장소로도 활용됨

이미지 삭제

  • 이미지 삭제는 단순하지 않으며, 태그 제거(언태그)만으로는 manifest 자체가 삭제되지 않음
  • 완전 삭제 절차:
    • (1) DELETE /v2/<repo>/manifests/<tag>로 태그 제거
    • (2) manifest를 digest로 조회해 참조 중인 모든 blob 확인
    • (3) 다른 manifest에서 공유 중이지 않은 blob만 선택적으로 삭제
    • (4) DELETE /v2/<repo>/blobs/<manifest-digest>로 manifest blob 삭제
  • 레지스트리는 콘텐츠 주소 지정 저장소이므로, 동일한 rootfs 레이어를 여러 이미지가 공유할 수 있으며, 삭제 시 해당 레이어를 참조하는 모든 이미지에 영향을 줌
  • 대안으로 모든 태그를 제거한 뒤 레지스트리의 가비지 컬렉션(garbage collection) 설정에 의존하는 방법도 있으나, 공용 레지스트리에서는 항상 활성화되어 있지 않음

멀티 플랫폼 이미지

  • 멀티 플랫폼 이미지는 레지스트리 API 구조 변경 없이 구현됨 — 엔드포인트 추가·수정 없이 기존 API를 그대로 활용
  • 구성 방식:
    • 각 단일 플랫폼 변형(amd64, arm64 등)을 개별 manifest와 함께 digest 기반으로 먼저 push
    • 이후 image index(manifest list) 라 불리는 상위 manifest를 태그와 함께 push
  • GET /v2/<repo>/manifests/<tag> 호출 시 단일 플랫폼 manifest 또는 image index 중 하나가 반환되며, 호출자는 반환된 문서의 content type으로 구분해야 함
  • 결과적으로 멀티 플랫폼 지원은 기존 구조에 간접 계층 하나와 index 문서 업로드/다운로드 단계 하나만 추가한 것

레지스트리 API 보호

  • OCI Distribution Spec은 인증 방식을 엄격히 정의하지 않으나, 대부분의 실제 레지스트리는 HTTP Basic 인증을 사용
  • 자격증명이 평문으로 전송되는 것을 막기 위해 반드시 HTTPS 위에서 운영해야 함

댓글과 토론