본문 바로가기
  • 오늘처럼
소프트웨어 아키텍처/Docker

Docker registry API - pull

by bluefriday 2021. 9. 22.
반응형

Docker Image 의 파일시스템

컨테이너 이미지를 저장하는 Docker Registry 를 통해 저장소에 이미지를 pull, push 할 수 있다. 'docker pull / docker push ' 명령어로 이루어지는 이러한 pull, push 는 내부적으로는 docker registry api 를 여러 번 호출하는 과정으로 구현된다. 이번에는 Docker Registry 가 제공하는 API 를 이용하여 docker pull 명령어를 구현해본다. 호출하는 API는 모두 공식 도커 해당문서에서 확인할수 있다.

docker registry 의 API 를 알아보기 전에 먼저 도커 레지스트리에 이미지가 저장되는 구조에 대해서 정리해보자. 자세한 내용은 해당 블로그의 포스팅을 참조하자.

멀티 레이어로 구성되어 있는 도커 이미지가 레지스트리에 저장될 때 각각의 레이어는 다음의 3가지 종류의 파일 형식으로 저장이 된다.

Manifest 레이어 (1개만 존재)  내용 : 이미지 메타(Config, Blob 레이어들 대한 정보)를 저장
 형식 : application/vnd.docker.distribution.manifest.v2+json
Config 레이어 (1개만 존재)  내용 : 이미지의 실행 플랫폼, OS 등에 대한 정보를 저장
 형식 : application/vnd.docker.container.image.v1+json
1개 이상의 Blob 레이어  내용 : 이미지 자체에 대한 레이어 blob 형식의 파일로 구성
 형식 : application/vnd.docker.image.rootfs.diff.tar.gzip

 

Image pull 의 단계

즉, 하나의 컨테이너 이미지를 받아온다는(pulling) 것은 위 3가지 형식의 파일을 다운로드 하는 것과 동일하다. 'docker pull' 명령어로 특정 이미지를 받아오게 되면 내부적으로 docker registry pull api 를 여러번 호출하여 위 manifest, config, blob(s) 들을 받아오게 된다. 레이어를 받아오는 순서는 다음과 같다.

  1. manifest 레이어 다운로드
  2. config 레이어 다운로드
  3. blobs 레이어 다운로드

 

테스트 환경 구축

이제 로컬 환경에 테스트용 docker registry 를 구축한 후에 테스트 이미지를 push 한다. 테스트 이미지의 이름(docker.io/hello-world:test) 은 임의의 이름을 사용하였기에, 실제 테스트 시에는 각자 개별적인 임의의 이미지를 선정하도록 하자

### 레지스트리 구동
mkdir -p /root/registry-api
docker run -d --name=test-registry -p 5000:5000 -v /root/registry-api:/var/lib/registry registry:latest

### 테스트 이미지 pull 후 태그변경하여 로컬 registry push
docker pull docker.io/hello-world:test
docker tag docker.io/hello-world:test localhost:5000/hello-world:test
docker push localhost:5000/hello-world:test

그리고 docker registry API 를 이용하여 이미지를 받아와서 결과적으로 docker pull 과 동일한 기능이 동작되는지 확인하자. 

 

1. manifest 레이어 다운로드

먼저 이미지의 manifest 레이어를 조회한 뒤 파일로 작성한다. 하단과 같이 image.manifest 파일로 저장한 후 해당 내용을 확인하자.

### 이미지의 manifest 조회
curl -X GET 저장소경로/v2/이미지명/manifest/태그명 -H "Accept: application/vnd.docker.distribution.manifest.v2+json"

### 실제 사용 예제
curl -X GET localhost:5000/v2/hello-world/manifests/test -H "Accept: application/vnd.docker.distribution.manifest.v2+json" > image.manifest

### image.manifest 파일의 내용
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": 1945,
      "digest": "sha256:8d147537fb7d1ac8895da4d55a5e53621949981e2e6460976dae812f83d84a44"
   },
   "layers": [
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 122224,
         "digest": "sha256:c6568d217a0023041ef9f729e8836b19f863bcdb612bb3a329ebc165539f5a80"
      },
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 13580365,
         "digest": "sha256:bc38a22c706b427217bcbd1a7ac7c8873e75efdd0e59d6b9f069b4b243db4b4b"
      }
   ]
}

간단하게 manifest 의 파일을 확인해보자. json 파일의 키 값을 통해 해당 manifest 가 "application/vnd.docker.distribution.manifest.v2+json" 형식으로 구성되어 있음을 알 수 있다. 여기서 'config' 필드는 위에서 언급한 config 레이어의 mediaType / size / digest 값을 가지고 있으며, 'layers' 필드는 blob 레이어에 대한 정보를 배열의 형태로 저장하게 된다. 이렇게 저장소 경로와 이미지명, 태그명을 이용하여 해당 이미지의 manifest 정보를 얻어낸 뒤에 manifest에서 config, blobs 레이어에 대한 정보를 확인하여 다음 단계에서 각 레이어를 받아올 수 있다.

 

2. config 레이어 다운로드

다음으로 config 레이어를 받아온다. config 레이어는 이미지의 지원 아키텍처 셋, 도커파일의 정보 등을 담고 있는 특수한 blobs 레이어의 일종으로 blobs 레이어와 동일한 API를 사용하여 얻을 수 있다. 가독성을 위하여 긴 digest 값의 이름을 6자로 줄여 표기하였다.

### config 값 얻어오기
curl -H "Accept: application/vnd.docker.image.rootfs.diff.tar.gzip" \
     -X GET 저장소명/v2/이미지명/blobs/sha256:이미지주소값

### 실제 사용 예제
curl -H "Accept: application/vnd.docker.image.rootfs.diff.tar.gzip" \
     -X GET http://localhost:5000/v2/hello-world/blobs/sha256:8d1475 > 8d1475

명령어의 실제 사용 예제에서는 config 레이어의 digest 값을 이용한다. 위에서 얻은 manifest 파일에 있는, config 레이어의 digest 값인 "8d147537fb7d1ac8895da4d55a5e53621949981e2e6460976dae812f83d84a44" 값을 사용한 것을 확인할 수 있다.

 

3. blobs 레이어 다운로드

이번에는 blobs 레이어를 받아온다. 여기서도 가독성을 위하여 digest 이름은 6자로 줄여 표기하였다.

### blob 레이어 얻어오기
curl -H "Accept: application/vnd.docker.image.rootfs.diff.tar.gzip" \
     -X GET 저장소명/v2/이미지명/blobs/sha256:주소지정값 


### 사용예제 : 1번째 blob 레이어 획득
curl -H "Accept: application/vnd.docker.image.rootfs.diff.tar.gzip" \
     -X GET http://localhost:5000/v2/hello-world/blobs/sha256:c6568d > c6568d

### 사용예제 : 2번째 blob 레이어 획득
curl -H "Accept: application/vnd.docker.image.rootfs.diff.tar.gzip" \
     -X GET http://localhost:5000/v2/hello-world/blobs/sha256:bc38a2 > bc38a2

이 테스트용 이미지는 2개의 blob 레이어를 포함하는 것을 위 manifest 파일에서 확인하였으며 각 blob 파일의 digest 값을 이용하여 config 파일과 동일한 명령어로 레이어를 각각 얻어올 수 있다.

 

이미지 파일 확인

이렇게 manifest, config, blobs 로 이미지의 모든 레이어를 파일로 저장하였다. 저장 결과는 다음과 같다.

[root@localhost:/] ls -al
total 13392
drwxr-xr-x 3 root root      264 Sep 22 14:59 .
drwxr-xr-x 7 root root       86 Sep 22 14:38 ..
-rw-r--r-- 1 root root     1945 Sep 22 14:59 8d147537fb7d1ac8895da4d55a5e53621949981e2e6460976dae812f83d84a44
-rw-r--r-- 1 root root 13580365 Sep 22 14:59 bc38a22c706b427217bcbd1a7ac7c8873e75efdd0e59d6b9f069b4b243db4b4b
-rw-r--r-- 1 root root   122224 Sep 22 14:59 c6568d217a0023041ef9f729e8836b19f863bcdb612bb3a329ebc165539f5a80
-rw-r--r-- 1 root root      739 Sep 22 14:50 image.manifest
[root@localhost:/] ls -al

초기 테스트 디렉토리인 '/root/registry-api' 경로 하위에 생성된 'docker/registry/v2' 디렉토리 밑에 있는 레이어 파일들과 동일한 파일임을 diff 명령어 등으로 확인할 수 있다.

이렇게 registry 가 제공하는 v2 api 를 이용하여, 특정 이미지의 레이어 파일을 로컬 환경에 저장하였다. 다음 포스팅에서는 역으로 로컬 환경에 저장한 레이어 파일을 개별 저장소에 push 하는 과정을 다루어본다.

댓글