TL;DR

  • 이미지는 레이어 묶음, 레지스트리는 그 보관소 → 캐시 덕에 Pull·Push 때 필요한 레이어만 이동
  • 매니페스트 (+ 리스트)가 “내 플랫폼에 필요한 레이어”만 가이드해 전송 최적화
  • Verified/Official/Golden 이미지로 신뢰도 확보

1. Docker 레지스트리 기본 개념

컨테이너 이미지를 저장 · 배포하는 서버(repository 서비스) 를 ‘레지스트리(registry)’라고 부른다
가장 널리 쓰이는 Docker Hub 외에도 AWS ECR, GitHub Container Registry, 그리고 직접 구축한 사내 레지스트리가 있다

레지스트리는 이미지를 통째로 보관하지 않는다. 대신 여러 개의 “레이어 (layer)” 아카이브를 조합해 하나의 이미지를 만든다
이 구조 덕분에 같은 레이어를 여러 이미지가 공유할 수 있고, 네트워크 전송량도 최소화된다.


2. 이미지 이름(Image Reference) 구조

[registry-domain]/[namespace]/[repository]:[tag]
 
<예시>
docker.io/diamol/golang:latest
registry-domain : 이미지가 저장된 레지스트리 (서버) 주소
  • 생략하면 기본값 docker.io(Docker Hub)
  • 사내 레지스트리의 경우 registry.my-corp.com 같은 형태
namespace : 작성자 또는 조직 계정
  • 네임스페이스가 다르면 같은 repo 이름이라도 충돌 없이 공존 가능
  • library/ubuntu처럼 공식 이미지는 특수 네임스페이스에 위치
repository : 실제 애플리케이션, 프로젝트 이름
  • 하나의 repo안에 여러 태그를 두어 버전 관리
tag : Repo 내부의 버전 식별자
  • 기본값 latest
    • “태그 생략 시 쓰이는 별칭”일 뿐 ‘가장 최신’과 동의어 아님
  • 불변 배포가 필요하면 sha256:abcdef… 처럼 digest (내용 해시)를 직접 지정

docker.io/diamol/golang:latest 는  Docker Hub에 있는, diamol 사용자가 관리하는 golang 레포의 latest 태그 이미지


3. 매니페스트(manifest) : 이미지 청사진

앞서 언급했듯이 컨테이너 이미지는 여러 레이어 (layer) 아카이브를 조립해서 만든다
매니페스트는 이 조립 방법을 설명하는 JSON 문서로, 레지스트리-클라이언트가 최초로 교환하는 메타데이터다

구성 요소핵심 역할
config 블롭 (config.json)컨테이너 런타임 설정 — Entrypoint, Cmd, Env, OS/Arch, 사용자 UID 등
layers 배열각 레이어의 SHA-256 digest·크기·MediaType 목록
(선택) manifest listlinux/amd64, linux/arm64 등 여러 플랫폼 매니페스트를 묶는 상위 인덱스

매니페스트는 “어떤 부품 (레이어)을 내려받아야 이 이미지가 조립-실행되는지” 를 알려 주는 청사진이며, 덕분에 클라이언트는 필요한 레이어만 골라 전송해 네트워크 비용을 최소화할 수 있다.


4. 이미지 전송 시 : 매니페스트가 이끄는 단계별 과정

4-1 이미지 Pull (레지스트리 → 클라이언트)
  1. 매니페스트 요청  

    • golang:1.22 참조를 해석해 레지스트리에서 매니페스트 (또는 manifest-list) 다운로드
  2. 플랫폼 매칭  

    • 예) mac-ARM이면 linux/arm64 서브 매니페스트 선택
  3. 로컬 캐시 대조  

    • 매니페스트 속 digest 목록 ↔ 로컬 DB 비교 → 없는 레이어만 GET
  4. 레이어 압축 해제 & 합치기  

    • 다운받은 tar.gz 레이어를 풀고 OverlayFS 등 유니언 FS로 계층을 합친 뒤, 최상단에 읽기-쓰기 레이어를 올리면 컨테이너 실행 준비 완료
4-2 이미지 Push (클라이언트 → 레지스트리)
  1. 해시 계산  

    • 각 레이어와 config.json에 SHA-256 digest 부여
  2. 중복 확인  

    • 해시를 레지스트리에 전송 → 이미 존재하면 “있다(HTTP 202)” 응답 → 업로드 생략
  3. 새 레이어만 업로드  

    • 없는 레이어를 PUT 전송, 레지스트리가 해시 검증 후 저장
  4. 매니페스트 업로드  

    • 마지막으로 레이어 목록·메타가 담긴 매니페스트 JSON PUSH
    • 멀티 아키텍처 이미지는 여러 매니페스트를 가리키는 manifest-list 도 함께 PUSH

5. 태그·버전 전략 

컨테이너 이미지를 관리할 땐 Semantic Versioning (major‧minor‧patch) 규칙이 기본이다
patch 숫자가 올라가면 단순 버그 수정, minor는 호환성을 유지한 기능 추가, major는 호환성이 깨질 만한 큰 변화라는 의미다

태그는 사람이 읽기 편한 별칭일 뿐이므로, 실제 배포 단계에서는 고정된 digest(sha256: …) 를 함께 사용해 동일 이미지를 보장하는 편이 안전하다

SemVer 예시
  • 1.2.5 patch 버전은 버그만 수정
  • 1.3.0 minor 버전은 새 기능을 추가하되 기존 API 유지
  • 2.0.0 major 버전은 호환성이 깨지는 변경 포함
태그 운용 팁
  • latest 태그는 로컬 개발·테스트에서만 사용하고 배포 스크립트에는 버전 태그나 digest를 명시
  • 롤링 업데이트가 필요한 서비스는 myapp:1.4(가변 태그)와 myapp:1.4-build567(고정 태그) 두 가지를 동시에 발행해 배포 단계별로 구분
  • 보안 패치를 적용할 때는 기존 태그를 덮어쓰지 말고 새 patch 태그(1.4.3)를 만들어 릴리스 후 changelog에 기록

7. 이미지 신뢰도 확보

공용 레지스트리에 올라온 이미지는 출처가 다양해 품질과 보안 수준이 제각각이다
배포 파이프라인이 신뢰할 수 있는 이미지만 사용하려면 출처·서명·취약점 스캔 세 가지 관점에서 검증해야 한다  

Verified Publisher
  • Docker Hub가 공식 파트너 기업에 부여하는 배지  
  • 서명과 자동 취약점 스캔을 통과한 이미지만 발행할 수 있어 신뢰도가 높다  
Official Image
  • nginx postgres 같은 대표 오픈소스를 커뮤니티가 유지 관리  
  • CI 파이프라인으로 최신 패치가 빠르게 반영되고 Dockerfile이 GitHub에 공개돼 투명성이 확보된다  
Golden Image
  • 조직 내부 표준 베이스 이미지  
  • 공통 에이전트 CA 인증서 프록시 설정 등을 포함해 모든 사내 Dockerfile이 상속하도록 해 일관된 보안 정책을 유지  
    FROM my-registry.internal/base/dotnet:6.0-golden