Özel bir docker kayıt defteri çalıştırıyorum ve latest
bir depodan tüm resimleri silmek istiyorum . Deponun tamamını silmek istemiyorum, sadece içindeki bazı resimler. API dosyaları bunu yapmanın bir yolu söz etmeyin, ama kesinlikle bu mümkün?
Özel bir docker kayıt defteri çalıştırıyorum ve latest
bir depodan tüm resimleri silmek istiyorum . Deponun tamamını silmek istemiyorum, sadece içindeki bazı resimler. API dosyaları bunu yapmanın bir yolu söz etmeyin, ama kesinlikle bu mümkün?
Yanıtlar:
Şu anda bu görev için Kayıt Defteri API'sını kullanamazsınız. Yalnızca bir havuzu veya belirli bir etiketi silmenizi sağlar.
Genel olarak, bir havuzun silinmesi, bu depoyla ilişkili tüm etiketlerin silineceği anlamına gelir.
Bir etiketi silmek, bir resim ile bir etiket arasındaki ilişkinin silineceği anlamına gelir.
Yukarıdakilerin hiçbiri tek bir görüntüyü silmez. Diskinizde kalırlar.
Bu geçici çözüm için docker görüntülerinizin yerel olarak depolanması gerekir.
Çözümünüz için geçici bir çözüm, en son etiketleri hariç tümünü silmek ve böylece ilişkili resimlere olan referansı kaldırmak olabilir. Daha sonra bu komut dosyasını , herhangi bir etiket tarafından kullanılmayan tüm görüntüleri veya kullanılan herhangi bir görüntünün atalarını kaldırmak için çalıştırabilirsiniz .
Büyük harfler (burada böyle bir görüntü grafiğini düşünün A
, B
, ...) kısa görüntü kimlikleri ve temsil <-
bir görüntü başka görüntüde dayandığını araçlar:
A <- B <- C <- D
Şimdi resme etiketler ekliyoruz:
A <- B <- C <- D
| |
| <version2>
<version1>
Burada, etiket <version1>
resme C
, etiket <version2>
ise resme referansta bulunur D
.
Sorunuzda, kaldırmak istediğinizi söylediniz
dışındaki tüm resimler
latest
. Şimdi, bu terminoloji tam olarak doğru değil. Görüntüleri ve etiketleri karıştırdınız. Grafiğe baktığımızda, etiketin <version2>
en son sürümü temsil ettiğini kabul edeceğinizi düşünüyorum . Aslında, bu soruya göre en son sürümü temsil eden bir etikete sahip olabilirsiniz:
A <- B <- C <- D
| |
| <version2>
| <latest>
<version1>
<latest>
Etiket resme referans verdiğinden, D
size soruyorum: gerçekten resim dışında hepsini silmek istiyor D
musunuz? Muhtemelen değil!
Etiketi <version1>
Docker REST API'sini kullanarak silerseniz bunu alırsınız:
A <- B <- C <- D
|
<version2>
<latest>
Unutmayın: Docker asla bir görüntüyü silmez! Olsa bile, bu görüntü bir görüntüyü silemez, çünkü görüntü etiketlenen C
görüntünün soyunun bir parçasıdır D
.
Bu komut dosyasını kullansanız bile , hiçbir görüntü silinmeyecektir.
Birisinin kayıt defterinizi ne zaman çekebileceğini veya kaydedebileceğini kontrol edebilmeniz koşuluyla (örneğin, REST arayüzünü devre dışı bırakarak). Bir görüntüyü temel alan başka bir resim yoksa ve ona hiçbir etiket referans göstermiyorsa, bir resmi resim grafiğinden silebilirsiniz.
Aşağıdaki grafikte, görüntü o Bildirimi D
edilir değil dayanan C
ama üzerinde B
. Bu nedenle, D
bağımlı değildir C
. <version1>
Bu grafikteki etiketi silerseniz , görüntü C
hiçbir resim tarafından kullanılmaz ve bu komut dosyası bunu kaldırabilir.
A <- B <--------- D
\ |
\ <version2>
\ <latest>
\ <- C
|
<version1>
Temizleme işleminden sonra görüntü grafiğiniz şöyle görünür:
A <- B <- D
|
<version2>
<latest>
İstediğiniz bu mu?
Benim kayıt defteri ile aynı sorunla karşılaştım sonra bir blog sayfasından aşağıda listelenen çözüm çalıştı. İşe yarıyor.
Bu URL'yi arayarak kataloglarınızı listeleyebilirsiniz:
http://YourPrivateRegistyIP:5000/v2/_catalog
Yanıt şu biçimde olacaktır:
{
"repositories": [
<name>,
...
]
}
Bu URL'yi çağırarak kataloğunuzun etiketlerini listeleyebilirsiniz:
http://YourPrivateRegistyIP:5000/v2/<name>/tags/list
Yanıt şu biçimde olacaktır:
{
"name": <name>,
"tags": [
<tag>,
...
]
}
Bu komutu docker kayıt defteri kapsayıcısında çalıştırabilirsiniz:
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)}'
Yanıt şu biçimde olacaktır:
sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073
Aşağıda verilen komutu manifest değeriyle çalıştırın:
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
Docker kayıt kapsayıcısında bu komutu çalıştırın:
bin/registry garbage-collect /etc/docker/registry/config.yml
İşte benim 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
Deleteing blob: /docker/...
" İle ilgili mesajlar da dahil olmak üzere komutlar başarılı oldu, ancak kullanılan disk alanını değiştirmedi. Bin / kayıt defteri kullanma github.com/docker/distribution v2.4.1 .
Docker-Content-Digest
bölüm yani küçük harf (liman işçisi motor v18.09.2 üzerinde test) olmalıdırcurl -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)}'
Mevcut v2
kayıt defteri artık üzerinden silinmeyi destekliyorDELETE /v2/<name>/manifests/<reference>
Bkz. Https://github.com/docker/distribution/blob/master/docs/spec/api.md#deleting-an-image
Çalışma kullanımı: https://github.com/byrnedo/docker-reg-tool
Düzenleme: Yukarıdaki bildirim <reference>
istekte bulunarak alınabilir
GET /v2/<name>/manifests/<tag>
ve Docker-Content-Digest
yanıttaki başlığı kontrol etme .
Edit 2: Kayıt defterinizi aşağıdaki env setiyle çalıştırmanız gerekebilir:
REGISTRY_STORAGE_DELETE_ENABLED="true"
Edit3: Bu disk alanını boşaltmak için çöp toplama çalıştırmanız gerekebilir: https://docs.docker.com/registry/garbage-collection/
DELETE
.
{"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}
Sorun 1
Bunun özel docker kayıt defteriniz olduğunu belirttiniz, bu nedenle muhtemelen sağladığınız bağlantı olan Hub kayıt defteri API belgesi yerine Kayıt Defteri API'sını kontrol etmeniz gerekir .
Sorun 2
docker kayıt defteri API'si bir istemci / sunucu protokolüdür, arka uçtaki görüntülerin kaldırılıp kaldırılmayacağı sunucunun uygulamasına bağlıdır. (Sanırım)
DELETE /v1/repositories/(namespace)/(repository)/tags/(tag*)
Detay açıklama
Aşağıda, sorularınız için anlayışım olarak açıklamanızdan şimdi nasıl çalıştığını gösteriyorum.
Özel docker kayıt defterini çalıştırdığınızda, varsayılanı kullanıyorum ve 5000
bağlantı noktasında dinliyorum
docker run -d -p 5000:5000 registry
Sonra yerel görüntüyü etiketleyip içine itiyorum.
$ 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}
Bundan sonra özel docker kayıt defterinizde var olup olmadığını kontrol etmek için Kayıt Defteri API'sını kullanabilirsiniz
$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags
{"latest": "e54ca5efa2e962582a223ca9810f7f1b62ea9b5c3975d14a5da79d3bf6020f37"}
Şimdi bu API kullanarak etiketi silebilirim !!
$ curl -X DELETE localhost:5000/v1/repositories/ubuntu/tags/latest
true
Tekrar kontrol edin, etiket özel kayıt sunucunuzda mevcut değil
$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags/latest
{"error": "Tag not found"}
registry
resimden silmenin bir yolunu arıyordum . Bir komut dosyası içinde SSHing yapmak ve çalıştırmak, ideal olmasa bile çalışır. Bir yan not olarak bunun hala eksik bir API olduğunu düşünüyorum - etiketleri silebilirsiniz, ancak /images
GETElerseniz artık tüm görüntü verilerini görürsünüz.
Bu gerçekten çirkin ama işe yarıyor, metin kayıt defterinde test ediliyor: 2.5.1. Silme özelliğini etkinleştirmek için yapılandırmayı güncelledikten sonra bile silme işleminin sorunsuz şekilde yapılmasını başaramadım. Kimlik almak gerçekten zordu, almak için giriş yapmak zorunda kaldı, belki bazı yanlış anlama. Her neyse, aşağıdaki işler:
Konteynere giriş
docker exec -it registry sh
Kapsayıcı ve kapsayıcı sürümünüzle eşleşen değişkenleri tanımlayın:
export NAME="google/cadvisor"
export VERSION="v0.24.1"
Kayıt defteri dizinine gidin:
cd /var/lib/registry/docker/registry/v2
Karma ile ilgili dosyaları silin:
find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
Manifestleri sil:
rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
Çıkış Yap
exit
GC'yi çalıştırın:
docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml
Her şey düzgün yapılmışsa, silinmiş lekeler hakkında bazı bilgiler gösterilir.
Tam olarak bunu yapan bazı müşteriler (Python, Ruby, vb.) Vardır. Benim zevkime göre, kayıt defteri sunucuma bir çalışma zamanı (örn. Python) yüklemek, sadece kayıt defterimi temizlemek için sürdürülebilir değildir!
Yani deckschrubber
benim çözümdür:
go get github.com/fraunhoferfokus/deckschrubber
$GOPATH/bin/deckschrubber
belirli bir yaştan daha eski görüntüler otomatik olarak silinir. Yaş kullanılarak belirtilebilir -year
, -month
, -day
veya bunların kombinasyonu:
$GOPATH/bin/deckschrubber -month 2 -day 13 -registry http://registry:5000
GÜNCELLEME : İşte deckschrubber hakkında kısa bir giriş .
deckschrubber
oldukça iyi - kurulumu çok kolay (tek ikili) ve görüntüleri isme (regex eşleşmesi ile) ve yaşa göre silmenizi sağlar.
ERRO[0000] Could not delete image! repo=.... tag=latest
: /
Kısaca;
1) Bir docker deposunun RepoDigest'leri için aşağıdaki komutu yazmanız gerekir;
## 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 kayıt defterini kullanın
##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
Başarılı bir çağırma için 202 Kabul edildi.
3-) Çöp Toplayıcıyı Çalıştırın
docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml
kayıt defteri - kayıt defteri kapsayıcı adı.
Daha ayrıntılı açıklama için bağlantı açıklamasını buraya girin
Bu docker görüntüsü, uzak v2 kayıt defterinden görüntüleri kaldırmak için kullanılabilecek bir bash betiği içerir: https://hub.docker.com/r/vidarl/remove_image_from_registry/
Bash Script Altında En son kayıt defteri dışında bulunan tüm etiketleri siler.
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 $2}' )
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
Bu Koşudan Sonra
docker exec $(docker ps | grep registry | awk '{print $1}') /bin/registry garbage-collect /etc/docker/registry/config.yml
Bu yanıta dayanan basit yakut komut dosyası : Registry_cleaner .
Yerel makinede çalıştırabilirsiniz:
./registry_cleaner.rb --host=https://registry.exmpl.com --repository=name --tags_count=4
Ve sonra kayıt defteri makinesinde lekeleri kaldırın /bin/registry garbage-collect /etc/docker/registry/config.yml
.
İşte Yavuz Sert'in cevabına dayanan bir senaryo. En son sürüm olmayan tüm etiketleri siler ve etiketleri 950'den büyüktür.
#!/usr/bin/env bash
CheckTag(){
Name=$1
Tag=$2
Skip=0
if [[ "${Tag}" == "latest" ]]; then
Skip=1
fi
if [[ "${Tag}" -ge "950" ]]; then
Skip=1
fi
if [[ "${Skip}" == "1" ]]; then
echo "skip ${Name} ${Tag}"
else
echo "delete ${Name} ${Tag}"
Sha=$(curl -v -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://127.0.0.1:5000/v2/${Name}/manifests/${Tag} 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}')
Sha="${Sha/$'\r'/}"
curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE "http://127.0.0.1:5000/v2/${Name}/manifests/${Sha}"
fi
}
ScanRepository(){
Name=$1
echo "Repository ${Name}"
curl -s http://127.0.0.1:5000/v2/${Name}/tags/list | jq '.tags[]' |
while IFS=$"\n" read -r line; do
line="${line%\"}"
line="${line#\"}"
CheckTag $Name $line
done
}
JqPath=$(which jq)
if [[ "x${JqPath}" == "x" ]]; then
echo "Couldn't find jq executable."
exit 2
fi
curl -s http://127.0.0.1:5000/v2/_catalog | jq '.repositories[]' |
while IFS=$"\n" read -r line; do
line="${line%\"}"
line="${line#\"}"
ScanRepository $line
done