Как удалить изображения из частного реестра docker?


Я запускаю частный реестр докеров, и я хочу удалить все изображения, но latest из репозитория. Я не хочу удалять весь репозиторий, только некоторые изображения внутри него. Элемент API docs не упоминайте способ сделать это, но, конечно, это возможно?

8 97

8 ответов:

в настоящее время вы не можете использовать API реестра для этой задачи. Он позволяет удалить только репозиторий или определенный тег.

в общем случае удаление репозитория означает, что все теги, связанные с этим РЕПО, удаляются.

удаление тега означает, что связь между изображением и тегом удаляется.

ни одно из вышеперечисленных не удалит ни одного изображения. Они остаются на вашем диск.


решение

для этого обходного пути вам нужно, чтобы ваши изображения докеров хранились локально.

обходным путем для вашего решения было бы удалить все, кроме последних тегов, и тем самым потенциально удалить ссылку на связанные изображения. Тогда вы можете запустить этот скрипт чтобы удалить все изображения, на которые не ссылается ни один тег или родословная любого используемого изображение.

терминология (изображения и теги)

рассмотрим графическое изображение, как это, где заглавные буквы (A,B, ...) представляют собой короткие идентификаторы изображений и <- означает, что изображение основано на другом изображении:

 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 is не на основе 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:

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 ()}'

ответ будет в следующем формате:

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:

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

здесь мой конфиг.в формате 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 заголовок в ответе.

1

Вы упомянули, что это был ваш личный реестр докеров, поэтому вам, вероятно, нужно проверить API реестра вместо Hub registry API doc, который является ссылкой, которую вы предоставили.

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. Мне не удалось получить удаление работает гладко даже после обновления конфигурации, чтобы включить удаление. Идентификатор было очень трудно получить, пришлось войти в систему, чтобы получить его, возможно, какое-то недоразумение. Во всяком случае, работает следующее:

  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 
    
  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.

этот образ docker включает в себя сценарий bash, который можно использовать для удаления изображений из удаленного реестра v2 : https://hub.docker.com/r/vidarl/remove_image_from_registry/

ниже Bash Script удаляет все теги, расположенные в реестре, кроме последнего.

for D in /registry-data/docker/registry/v2/repositories/*; do
if [ -d "${D}" ]; then
    if [ -z "$(ls -A ${D}/_manifests/tags/)" ]; then
        echo ''
    else
        for R in $(ls -t ${D}/_manifests/tags/ | tail -n +2); do
            digest=$(curl -k -I -s -H -X GET http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/${R} -H 'accept: application/vnd.docker.distribution.manifest.v2+json'  | grep Docker-Content-Digest | awk '{print }' )
            url="http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/$digest"
            url=${url%$'\r'}
            curl -X DELETE -k -I -s   $url -H 'accept: application/vnd.docker.distribution.manifest.v2+json' 
        done
    fi
fi
done

после этого запустить

docker exec $(docker ps | grep registry | awk '{print }') /bin/registry garbage-collect /etc/docker/registry/config.yml