[docker] 개인 도커 레지스트리에서 이미지를 삭제하는 방법은 무엇입니까?

개인 도커 레지스트리를 실행 latest하고 리포지토리에서 이미지를 제외한 모든 이미지를 삭제하고 싶습니다 . 전체 저장소를 삭제하고 싶지 않으며 그 안에있는 이미지 중 일부만 삭제하고 싶습니다. API 문서는 이 작업을 수행 할 수있는 방법을 언급하지 않지만, 분명히 그것은 가능?



답변

현재 해당 작업에 레지스트리 API를 사용할 수 없습니다. 리포지토리 또는 특정 태그 만 삭제할 수 있습니다.

일반적으로 리포지토리를 삭제하면이 리포지토리와 관련된 모든 태그가 삭제됩니다.

태그를 삭제하면 이미지와 태그 간의 연결이 삭제됩니다.

위의 어느 것도 단일 이미지를 삭제하지 않습니다. 그들은 당신의 디스크에 남아 있습니다.


해결 방법

이 문제를 해결하려면 도커 이미지를 로컬로 저장해야합니다.

솔루션의 해결 방법은 최신 태그를 제외한 모든 태그를 삭제하여 관련 이미지에 대한 참조를 제거하는 것입니다. 그런 다음 이 스크립트 를 실행 하여 태그 나 사용 된 이미지의 조상에서 참조하지 않는 모든 이미지를 제거 할 수 있습니다 .

용어 (이미지 및 태그)

대문자는 (여기서, 이와 같은 화상 그래프 고려 A, B…) 짧은 화상 ID와 대표 <-화상이 다른 화상에 기초되는 것을 의미 :

 A <- B <- C <- D

이제 그림에 태그를 추가합니다 :

 A <- B <- C <- D
           |    |
           |    <version2>
           <version1>

여기서 태그 <version1>는 이미지 C<version2>참조하고 태그 는 이미지를 참조합니다 D.

질문 다듬기

귀하의 질문에 당신은 당신이 제거하고 싶다고 말했다

모든 이미지를 제외한 latest

. 이제이 용어는 정확하지 않습니다. 이미지와 태그를 혼합했습니다. 그래프를 보면 태그 <version2>가 최신 버전을 나타내는 것에 동의한다고 생각합니다 . 실제로이 질문 에 따르면 최신 버전을 나타내는 태그를 사용할 수 있습니다.

 A <- B <- C <- D
           |    |
           |    <version2>
           |    <latest>
           <version1>

<latest>태그가 이미지를 참조 하기 때문에 D나는 당신에게 묻습니다 : 당신은 정말로 이미지를 제외한 모든 것을 삭제 하시겠습니까 D? 아마 아닙니다!

태그를 삭제하면 어떻게됩니까?

<version1>Docker REST API를 사용 하여 태그 를 삭제하면 다음을 얻을 수 있습니다.

 A <- B <- C <- D
                |
                <version2>
                <latest>

기억하십시오 : Docker는 이미지를 절대 삭제하지 않습니다! 이 경우에도 C이미지 D는 태그가 지정된 이미지의 상위 항목 이므로 이미지를 삭제할 수 없습니다 .

이 스크립트 를 사용하더라도 이미지는 삭제되지 않습니다.

이미지를 삭제할 수있는 경우

누군가가 레지스트리를 가져 오거나 푸시 할 수있는시기를 제어 할 수있는 조건 하에서 (예 : REST 인터페이스 비활성화). 이미지를 기반으로하는 다른 이미지가없고 이미지를 참조하지 않는 경우 이미지 그래프에서 이미지를 삭제할 수 있습니다.

다음 그래프, 이미지가 통지 D되어 있지 기반으로 C하지만,에 B. 따라서에 D의존하지 않습니다 C. <version1>이 그래프에서 태그를 삭제 하면 이미지 C가 이미지 를 사용하지 않으며이 스크립트 는이를 제거 할 수 있습니다.

 A <- B <--------- D
      \            |
       \           <version2>
        \          <latest>
         \ <- C
              |
              <version1>

정리 후 이미지 그래프는 다음과 같습니다.

 A <- B <- D
           |
           <version2>
           <latest>

이것이 당신이 원하는 것입니까?


답변

내 레지스트리와 동일한 문제에 직면 한 다음 블로그 페이지에서 아래 나열된 솔루션을 시도했습니다. 효과가있다.

1 단계 : 카탈로그 나열

이 URL을 호출하여 카탈로그를 나열 할 수 있습니다.

http://YourPrivateRegistyIP:5000/v2/_catalog

응답 형식은 다음과 같습니다.

{
  "repositories": [
    <name>,
    ...
  ]
}

2 단계 : 관련 카탈로그에 대한 태그 나열

이 URL을 호출하여 카탈로그의 태그를 나열 할 수 있습니다.

http://YourPrivateRegistyIP:5000/v2/<name>/tags/list

응답 형식은 다음과 같습니다.

{
"name": <name>,
"tags": [
    <tag>,
    ...
]

}

3 단계 : 관련 태그의 매니페스트 값 나열

docker registry container에서이 명령을 실행할 수 있습니다.

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost:5000/v2/<name>/manifests/<tag> 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}'

응답 형식은 다음과 같습니다.

sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

매니페스트 값으로 아래 제공된 명령을 실행하십시오.

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/<name>/manifests/sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

4 단계 : 표시된 매니페스트 삭제

docker registy 컨테이너에서이 명령을 실행하십시오.

bin/registry garbage-collect  /etc/docker/registry/config.yml

여기 내 config.yml입니다

root@c695814325f4:/etc# cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
  service: registry
storage:
    cache:
        blobdescriptor: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
    delete:
        enabled: true
http:
    addr: :5000
    headers:
        X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3


답변

현재 v2레지스트리는 다음을 통한 삭제를 지원합니다.DELETE /v2/<name>/manifests/<reference>

참조 : https://github.com/docker/distribution/blob/master/docs/spec/api.md#deleting-an-image

작업 사용법 :
https://github.com/byrnedo/docker-reg-tool

편집 : <reference>위 의 매니페스트 는 요청에서 검색 할 수 있습니다

GET /v2/<name>/manifests/<tag>

Docker-Content-Digest응답 에서 헤더를 확인하는 단계 .

편집 2 : 다음 env 세트로 레지스트리를 실행해야 할 수도 있습니다.

REGISTRY_STORAGE_DELETE_ENABLED="true"

Edit3 :이 디스크 공간을 확보하기 위해 가비지 수집을 실행해야 할 수도 있습니다 :
https://docs.docker.com/registry/garbage-collection/


답변

문제 1

개인 도커 레지스트리라고 언급 했으므로 제공 한 링크 인 Hub registry API doc 대신 Registry API 를 확인해야합니다 .

문제 2

docker registry API는 클라이언트 / 서버 프로토콜이며 백엔드에서 이미지를 제거할지 여부는 서버의 구현에 달려 있습니다. (추측)

DELETE /v1/repositories/(namespace)/(repository)/tags/(tag*)

세부 설명

아래는 귀하의 질문에 대한 나의 이해로서 귀하의 설명에서 현재 어떻게 작동하는지 보여줍니다.

개인 도커 레지스트리를 실행하면 기본 디렉토리를 사용하고 5000포트 에서 수신 대기합니다.

docker run -d -p 5000:5000 registry

그런 다음 로컬 이미지에 태그를 지정하고 밀어 넣습니다.

$ docker tag ubuntu localhost:5000/ubuntu
$ docker push localhost:5000/ubuntu
The push refers to a repository [localhost:5000/ubuntu] (len: 1)
Sending image list
Pushing repository localhost:5000/ubuntu (1 tags)
511136ea3c5a: Image successfully pushed
d7ac5e4f1812: Image successfully pushed
2f4b4d6a4a06: Image successfully pushed
83ff768040a0: Image successfully pushed
6c37f792ddac: Image successfully pushed
e54ca5efa2e9: Image successfully pushed
Pushing tag for rev [e54ca5efa2e9] on {http://localhost:5000/v1/repositories/ubuntu/tags/latest}

그런 다음 Registry API 를 사용 하여 개인 도커 레지스트리에 존재하는지 확인할 수 있습니다.

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags
{"latest": "e54ca5efa2e962582a223ca9810f7f1b62ea9b5c3975d14a5da79d3bf6020f37"}

이제 해당 API를 사용하여 태그를 삭제할 수 있습니다 !!

$ curl -X DELETE localhost:5000/v1/repositories/ubuntu/tags/latest
true

다시 확인하십시오. 개인 레지스트리 서버에 태그가 없습니다

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags/latest
{"error": "Tag not found"}


답변

이것은 실제로 추악하지만 작동하지만 텍스트는 레지스트리에서 테스트되었습니다 : 2.5.1. 삭제를 활성화하기 위해 구성을 업데이트 한 후에도 삭제가 원활하게 작동하지 못했습니다. ID를 찾기가 정말 어려웠으며, 로그인하기 위해 로그인해야했습니다. 어쨌든 다음과 같이 작동합니다.

  1. 컨테이너에 로그인

    docker exec -it registry sh
    
  2. 컨테이너 및 컨테이너 버전과 일치하는 변수를 정의하십시오.

    export NAME="google/cadvisor"
    export VERSION="v0.24.1"
    
  3. 레지스트리 디렉토리로 이동하십시오.

    cd /var/lib/registry/docker/registry/v2
    
  4. 해시와 관련된 파일을 삭제하십시오.

    find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
    
  5. 매니페스트 삭제 :

    rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
    
  6. 로그 아웃

    exit
    
  7. GC를 실행하십시오.

    docker exec -it registry  bin/registry garbage-collect  /etc/docker/registry/config.yml
    
  8. 모든 작업이 올바르게 완료되면 삭제 된 얼룩에 대한 정보가 표시됩니다.


답변

정확히 수행하는 클라이언트 (Python, Ruby 등)가 있습니다. 내 취향을 위해 레지스트리 서버에 런타임 (예 : Python)을 설치하는 것이 아니라 레지스트리를 유지하기 위해 지속 가능하지 않습니다!


그래서 deckschrubber내 솔루션입니다 :

go get github.com/fraunhoferfokus/deckschrubber
$GOPATH/bin/deckschrubber

특정 연령보다 오래된 이미지는 자동으로 삭제됩니다. 나이를 사용하여 지정할 수 있습니다 -year, -month, -day, 또는 이들의 조합 :

$GOPATH/bin/deckschrubber -month 2 -day 13 -registry http://registry:5000

업데이트 : deckschrubber에 대한 간단한 소개 입니다.


답변

간단히;

1) docker repo의 RepoDigests에 다음 명령을 입력해야합니다.

## docker inspect <registry-host>:<registry-port>/<image-name>:<tag>
> docker inspect 174.24.100.50:8448/example-image:latest


[
    {
        "Id": "sha256:16c5af74ed970b1671fe095e063e255e0160900a0e12e1f8a93d75afe2fb860c",
        "RepoTags": [
            "174.24.100.50:8448/example-image:latest",
            "example-image:latest"
        ],
        "RepoDigests": [
            "174.24.100.50:8448/example-image@sha256:5580b2110c65a1f2567eeacae18a3aec0a31d88d2504aa257a2fecf4f47695e6"
        ],
...
...

$ {digest} = sha256 : 5580b2110c65a1f2567eeacae18a3aec0a31d88d2504aa257a2fecf4f47695e6

2) 레지스트리 REST API 사용

  ##curl -u username:password -vk -X DELETE registry-host>:<registry-port>/v2/<image-name>/manifests/${digest}


  >curl -u example-user:example-password -vk -X DELETE http://174.24.100.50:8448/v2/example-image/manifests/sha256:5580b2110c65a1f2567eeacae18a3aec0a31d88d2504aa257a2fecf4f47695e6

성공적인 호출을 위해서는 202 Accepted를 받아야합니다.

3) 가비지 콜렉터 실행

docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml

registry — 레지스트리 컨테이너 이름입니다.

자세한 설명을 보려면 여기에 링크 설명을 입력하십시오