# 컨테이너 레지스트리의 작동 원리: 이미지 직접 Push/Pull하기

> Clean Markdown view of GeekNews topic #30004. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=30004](https://news.hada.io/topic?id=30004)
- GeekNews Markdown: [https://news.hada.io/topic/30004.md](https://news.hada.io/topic/30004.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-30T09:27:01+09:00
- Updated: 2026-05-30T09:27:01+09:00
- Original source: [labs.iximiuz.com](https://labs.iximiuz.com/tutorials/container-registry-from-scratch)
- Points: 1
- Comments: 0

## Topic Body

- **컨테이너 레지스트리**는 겉보기엔 단순하지만, 잘못된 태그, 플랫폼 불일치, 레이어 누락, 실제 삭제 실패 같은 문제를 디버깅하려면 내부 동작 원리를 반드시 이해해야 함  
- 레지스트리의 핵심은 **콘텐츠 주소 지정 방식(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/&lt;repo&gt;/blobs/&lt;digest&gt;`로 바로 수행 가능  
  
### 이미지 Push  
  
- 이미지 push 절차: (1) 각 **rootfs 레이어** blob 업로드 → (2) **image configuration** blob 업로드 → (3) 모든 digest를 하나의 JSON 문서로 묶는 **manifest** 파일 push  
- manifest는 `PUT /v2/&lt;repo&gt;/manifests/&lt;tag&gt;` 엔드포인트로 업로드하며, 이 시점에 태그가 생성됨  
- 실제 클라이언트(예: `docker push`)는 blob 업로드를 병렬로 수행하나, 원리 이해를 위해 순차 처리도 가능  
- 이미지 디렉터리 구성 예시: `config.json`, `layer-1.tar.gz`, `layer-2.tar.gz`, `manifest.json`  
  
### 태그 목록 조회  
  
- `GET /v2/&lt;repo&gt;/tags/list` 엔드포인트로 특정 레포지터리의 **모든 태그 목록** 조회 가능  
- 이 기능은 `docker` CLI에서는 노출되지 않으며, `curl` 또는 `crane`, `regctl` 같은 도구로만 접근 가능  
  - `crane`, `regctl`은 동일 엔드포인트를 `ls` 명령으로 래핑한 것  
  
### 이미지 Pull  
  
- pull 절차는 push의 역순: (1) `GET /v2/&lt;repo&gt;/manifests/&lt;tag&gt;`로 **manifest 조회** → (2) manifest에 명시된 digest로 **모든 blob 다운로드**  
- 현대 manifest는 rootfs 레이어·이미지 설정 외에도 **Helm 차트, SBOM, 출처 증명(provenance attestation), LLM 가중치** 등 임의 아티팩트를 blob으로 참조하는 범용 저장소로도 활용됨  
  
### 이미지 삭제  
  
- 이미지 삭제는 단순하지 않으며, **태그 제거(언태그)만으로는 manifest 자체가 삭제되지 않음**  
- 완전 삭제 절차:  
  - (1) `DELETE /v2/&lt;repo&gt;/manifests/&lt;tag&gt;`로 태그 제거  
  - (2) manifest를 digest로 조회해 참조 중인 모든 blob 확인  
  - (3) **다른 manifest에서 공유 중이지 않은 blob만** 선택적으로 삭제  
  - (4) `DELETE /v2/&lt;repo&gt;/blobs/&lt;manifest-digest&gt;`로 manifest blob 삭제  
- 레지스트리는 콘텐츠 주소 지정 저장소이므로, 동일한 rootfs 레이어를 여러 이미지가 공유할 수 있으며, 삭제 시 해당 레이어를 참조하는 **모든 이미지에 영향**을 줌  
- 대안으로 모든 태그를 제거한 뒤 레지스트리의 **가비지 컬렉션(garbage collection)** 설정에 의존하는 방법도 있으나, 공용 레지스트리에서는 항상 활성화되어 있지 않음  
  
### 멀티 플랫폼 이미지  
  
- 멀티 플랫폼 이미지는 **레지스트리 API 구조 변경 없이** 구현됨 — 엔드포인트 추가·수정 없이 기존 API를 그대로 활용  
- 구성 방식:  
  - 각 단일 플랫폼 변형(amd64, arm64 등)을 개별 manifest와 함께 **digest 기반으로 먼저 push**  
  - 이후 **image index(manifest list)** 라 불리는 상위 manifest를 태그와 함께 push  
- `GET /v2/&lt;repo&gt;/manifests/&lt;tag&gt;` 호출 시 단일 플랫폼 manifest 또는 image index 중 하나가 반환되며, 호출자는 반환된 문서의 **content type**으로 구분해야 함  
- 결과적으로 멀티 플랫폼 지원은 기존 구조에 **간접 계층 하나와 index 문서 업로드/다운로드 단계 하나**만 추가한 것  
  
### 레지스트리 API 보호  
  
- OCI Distribution Spec은 인증 방식을 엄격히 정의하지 않으나, 대부분의 실제 레지스트리는 **HTTP Basic 인증**을 사용  
- 자격증명이 평문으로 전송되는 것을 막기 위해 반드시 **HTTPS** 위에서 운영해야 함

## Comments



_No public comments on this page._
