도커 레지스트리 서버 및 클라이언트 PC에서 push를 통해 레지스트리에 등록한 이미지들을 삭제하는 방법을 확인한다. 해당 사설 레지스트리에 있는 이미지를 지우는 작업은 레지스트리 컨테이너를 실행하고 있는 PC에서만 수행할 수 있다.

매니페스트(manifests) 확인

삭제하려는 이미지 이름 확인

curl 명령어를 통해 삭제하려는 이미지 이름을 확인한다. 이전 게시물에서 사용하고 있는 172.16.10.7 IP를 예시에서 계속 사용하겠다.

$ curl https://172.16.10.7:5000/v2/_catalog

결과 출력으로는 현재 레지스트리에 등록된 이미지 이름이 나온다. ‘ubuntu’ 이미지가 존재하는 것을 확인할 수 있다.

{"repositories":["ubuntu"]}

삭제하려는 태그 확인

앞에서 얻은 이미지 이름의 태그 리스트를 확인하여 내가 삭제를 원하는 {이미지}:{태그} 조합을 확인할 수 있다. 여전히 curl 명령어를 사용한다.

$ curl https://172.16.10.7:5000/v2/ubuntu/tags/list

결과 출력은 ubuntu 이미지가 가지고 있는 태그들을 확인할 수 있다. 우리는 아래에 보이는 출력 중에서 16.04 태그의 이미지를 삭제해볼 것이다.

{"name":"ubuntu","tags":["16.04","latest","18.04"]}

매니페스트 정보 확인

도커 이미지는 이미지 자체에 대한 정보인 매니페스트와 실제 이미지를 구성하는 레이어 정보로 나뉘어진다. 이 두 가지는 고유 ID가 부여된 다이제스트(digest)라는 값을 가진다. 이 값을 일단 확인한다.

curl 명령어를 사용할 때 아래 예시에 있는 --header 부분을 그대로 적어준다. 헤더는 "Accept: application/vnd.docker.distribution.mannifest.v2+json" 값을 가진다. 추가적으로 -i 옵션을 넣어줘야 docker-content-digest 값을 확인할 수 있다.

# curl -i --header {헤더내용} https://{ip}:5000/v2/{imagename}/manifests/{tag}

$ curl -i --header "Accept: application/vnd.docker.distribution.mannifest.v2+json" \
https://172.16.10.7:5000/v2/ubuntu/manifests/16.04

출력이 나오면 해당 출력을 잘 확인해야한다. 아래의 내용 중에서 우리는 3번째 줄의 docker-content-digest 와 중간부터 아래에 여러개 들어있는 layers - digest 값을 사용할 것 이다. 필요없는 부분은 일부 생략하여 표현하겠다.

HTTP/2 200 
content-type: application/vnd.docker.distribution.manifest.v2+json
docker-content-digest: sha256:114bbce1997fa476da56c3958cb3ca13269a54b0a97dfd3667543c7778287bf2
docker-distribution-api-version: registry/2.0
...
...

{
   "schemaVersion": 2,
   ...,
   ...
   },
   "layers": [
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 46496785,
         "digest": "sha256:61e03ba1d4149ac4eb681c6bf75aef8ac4b3f0d6fbb08e9623c4089889396fc8"
      },
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 849,
         "digest": "sha256:4afb39f216bd4e336f9b78584bae0f6bcb77150107471d8d67d3b8abfbdea46a"
      },
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 528,
         "digest": "sha256:e489abdc9f902f737bfef2c0c7ff5c35ca9b3ca11e73405a472f31a25f2dcc69"
      },
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": 169,
         "digest": "sha256:999fff7bcc2450fcf1210182802f3907e35cd7cf7569568bd2a179b9144d9c57"
      }
   ]

매니페스트 다이제스트를 통한 이미지 삭제

위의 매니페스트 출력 결과에서 docker-content-digest 의 값을 보면 sha256:114bbce1997fa476da56c3958cb3ca13269a54b0a97dfd3667543c7778287bf2 인 것을 확인할 수 있다. curl 명령어를 통해 지우는 요청을 보내는데 형식은 아래와 같다. -v 옵션은 verbose의 약자로 실행 결과를 좀 더 자세히 출력해준다.

# DELETE /v2/{이미지이름}/manifests/{매니페스트 다이제스트}

$ curl -X DELETE -v https://172.16.20.90:5000/v2/ubuntu/manifests/sha256:114bbce1997fa476da56c3958cb3ca13269a54b0a97dfd3667543c7778287bf2

삭제에 성공하면 출력은 다음과 같다. 앞부분은 상당부분 생략하고 아래의 결과를 보면 된다. 성공 여부는 HTTP/2의 요청이 202 코드를 반환 했기에 성공했음을 확인할 수 있다.

...
...
...

> DELETE /v2/ubuntu/manifests/sha256:114bbce1997fa476da56c3958cb3ca13269a54b0a97dfd3667543c7778287bf2 HTTP/2
> Host: 172.16.10.7:5000
> User-Agent: curl/7.58.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 202 
< docker-distribution-api-version: registry/2.0
< x-content-type-options: nosniff

...
...

에러

혹시 아래와 같은 에러를 발생 시킬 수도 있다. 해당 오류의 원인은 현재 실행되고 있는 레지스트리 컨테이너가 등록된 이미지를 삭제하는 기능 자체를 포함하지 않기 때문이다.

{"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported","detail":{}}]}

위와 같은 아래가 발생하는 상황이라면 애초에 레지스트리 컨테이너를 환경변수를 추가하여 다시 실행해야한다. 추가해야할 환경변수는 REGISTRY_STORAGE_DELETE_ENABLED=true 이다. 이전 게시글의 레지스트리 컨테이너 실행방법에 해당 환경변수를 추가해서 다시 실행한다.

docker run -d -p 5000:5000 --restart=always --name sonregistry \
-v /home/smarteye/docker-registry/volume/:/data \
-v /home/smarteye/docker-registry/certs/:/certs \
-e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/server.key \
-e REGISTRY_STORAGE_DELETE_ENABLED=true
registry:2.6

레이어 다이제스트를 통한 레이어 삭제

위의 매니페스트 다이제스트를 통한 이미지 삭제를 했으니 레이어 삭제도 비슷하지만, 완전히 같은 것은 아니다. 일단 확인한 다이제스트 정보를 확인하면 다음과 같다. 총 4개이다.

sha256:61e03ba1d4149ac4eb681c6bf75aef8ac4b3f0d6fbb08e9623c4089889396fc8
sha256:4afb39f216bd4e336f9b78584bae0f6bcb77150107471d8d67d3b8abfbdea46a
sha256:e489abdc9f902f737bfef2c0c7ff5c35ca9b3ca11e73405a472f31a25f2dcc69
sha256:999fff7bcc2450fcf1210182802f3907e35cd7cf7569568bd2a179b9144d9c57

레이어 다이제스트는 다음과 같은 형식으로 이용해 삭제한다.

# DELETE /v2/{이미지이름}/blobs/{레이어 다이제스트}

$ curl -X DELETE -v HTTPS://172.16.20.90:5000/v2/ubuntu/blobs/sha256:61e03ba1d4149ac4eb681c6bf75aef8ac4b3f0d6fbb08e9623c4089889396fc8

$ curl -X DELETE -v HTTPS://172.16.20.90:5000/v2/ubuntu/blobs/sha256:4afb39f216bd4e336f9b78584bae0f6bcb77150107471d8d67d3b8abfbdea46a

...

매니페스트 다이제스트를 삭제할 때와 마찬가지로 아래와 같이 HTTP/2 요청의 응답이 202 인 것을 확인한다면 제대로 지워진 것이다. 이를 레이어의 갯수(다이제스트 수)만큼 수행하면 된다.

...
...

> DELETE /v2/ubuntu/blobs/sha256:4afb39f216bd4e336f9b78584bae0f6bcb77150107471d8d67d3b8abfbdea46a HTTP/2
> Host: 172.16.20.90:5000
> User-Agent: curl/7.58.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 202 
HTTP/2 202 
< docker-distribution-api-version: registry/2.0
docker-distribution-api-version: registry/2.0
< x-content-type-options: nosniff
x-content-type-options: nosniff

...
...

Leave a comment