ฉันเรียกใช้รีจิสทรีนักเทียบท่าส่วนตัวและฉันต้องการลบภาพทั้งหมดยกเว้นlatest
จากที่เก็บ ฉันไม่ต้องการลบพื้นที่เก็บข้อมูลทั้งหมดเพียงบางส่วนของภาพภายใน เอกสาร APIไม่ได้กล่าวถึงวิธีการที่จะทำเช่นนี้ แต่แน่นอนว่ามันเป็นไปได้หรือไม่
ฉันเรียกใช้รีจิสทรีนักเทียบท่าส่วนตัวและฉันต้องการลบภาพทั้งหมดยกเว้นlatest
จากที่เก็บ ฉันไม่ต้องการลบพื้นที่เก็บข้อมูลทั้งหมดเพียงบางส่วนของภาพภายใน เอกสาร APIไม่ได้กล่าวถึงวิธีการที่จะทำเช่นนี้ แต่แน่นอนว่ามันเป็นไปได้หรือไม่
คำตอบ:
ขณะนี้คุณไม่สามารถใช้ Registry API สำหรับงานนั้นได้ อนุญาตให้คุณลบที่เก็บหรือแท็กเฉพาะเท่านั้น
โดยทั่วไปการลบที่เก็บหมายความว่าแท็กทั้งหมดที่เกี่ยวข้องกับ repo นี้จะถูกลบ
การลบแท็กหมายความว่าการเชื่อมโยงระหว่างรูปภาพและแท็กจะถูกลบ
ไม่มีการข้างต้นจะลบภาพเดียว พวกเขาจะเหลืออยู่บนดิสก์ของคุณ
สำหรับวิธีแก้ปัญหานี้คุณต้องจัดเก็บภาพนักเทียบท่าไว้ในเครื่อง
วิธีแก้ปัญหาสำหรับโซลูชันของคุณคือการลบทั้งหมดยกเว้นแท็กล่าสุดและอาจลบการอ้างอิงไปยังรูปภาพที่เกี่ยวข้อง จากนั้นคุณสามารถเรียกใช้สคริปต์นี้เพื่อลบภาพทั้งหมดที่ไม่ได้อ้างอิงโดยแท็กใด ๆ หรือบรรพบุรุษของรูปภาพที่ใช้
ลองพิจารณากราฟภาพแบบนี้โดยที่ตัวอักษรพิมพ์ใหญ่ ( 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>
โปรดจำไว้ว่า:นักเทียบท่าจะไม่ลบภาพ! แม้ว่าจะเป็นเช่นนั้นในกรณีนี้มันไม่สามารถลบรูปภาพได้เนื่องจากรูปภาพC
เป็นส่วนหนึ่งของบรรพบุรุษสำหรับรูปภาพD
ที่ถูกแท็ก
แม้ว่าคุณจะใช้สคริปต์นี้จะไม่มีการลบภาพใด ๆ
ภายใต้เงื่อนไขที่คุณสามารถควบคุมได้เมื่อใครบางคนสามารถดึงหรือดันไปยังรีจิสทรีของคุณ (เช่นโดยการปิดการใช้งานส่วนต่อประสาน REST) คุณสามารถลบภาพออกจากกราฟภาพหากไม่มีภาพอื่นอ้างอิงและไม่มีแท็กที่อ้างถึง
โปรดสังเกตว่าในกราฟต่อไปนี้รูปภาพไม่ได้D
เป็นพื้นฐานแต่เป็น ดังนั้นไม่ขึ้นอยู่กับ หากคุณลบแท็กในกราฟนี้ภาพจะไม่ถูกใช้โดยภาพใด ๆ และสคริปต์นี้สามารถลบออกได้C
B
D
C
<version1>
C
A <- B <--------- D
\ |
\ <version2>
\ <latest>
\ <- C
|
<version1>
หลังจากล้างข้อมูลกราฟภาพของคุณจะเป็นดังนี้:
A <- B <- D
|
<version2>
<latest>
นี่คือสิ่งที่คุณต้องการ?
ฉันประสบปัญหาเดียวกันกับรีจิสตรีของฉันจากนั้นฉันลองใช้วิธีแก้ไขด้านล่างจากหน้าบล็อก มันได้ผล.
คุณสามารถแสดงรายการแคตตาล็อกของคุณโดยเรียก url นี้:
http://YourPrivateRegistyIP:5000/v2/_catalog
การตอบสนองจะอยู่ในรูปแบบต่อไปนี้:
{
"repositories": [
<name>,
...
]
}
คุณสามารถแสดงรายการแท็กของแคตตาล็อกของคุณโดยเรียก url นี้:
http://YourPrivateRegistyIP:5000/v2/<name>/tags/list
การตอบสนองจะอยู่ในรูปแบบต่อไปนี้:
{
"name": <name>,
"tags": [
<tag>,
...
]
}
คุณสามารถเรียกใช้คำสั่งนี้ในคอนเทนเนอร์รีจิสตรี 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 ($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
รันคำสั่งนี้ในคอนเทนเนอร์ที่ลงทะเบียนนักเทียบท่าของคุณ:
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
Deleteing blob: /docker/...
" แต่ไม่ได้เปลี่ยนพื้นที่ดิสก์ที่ใช้ ใช้bin / รีจิสทรี github.com/docker/distribution v2.4.1
Docker-Content-Digest
ส่วนหนึ่งควรจะอยู่ในตัวพิมพ์เล็ก (ทดสอบกับเครื่องยนต์ v18.09.2 นักเทียบท่า) เช่น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)}'
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"
แก้ไข 3: คุณอาจต้องเรียกใช้คอลเลกชันขยะเพื่อเพิ่มพื้นที่ว่างในดิสก์: https://docs.docker.com/registry/garbage-collection/
DELETE
นี้เป็นสิ่งจำเป็นในการแปลแท็กเป็นสิ่งที่จะส่งผ่านไป
{"errors":[{"code":"UNSUPPORTED","message":"The operation is unsupported."}]}
ปัญหาที่ 1
คุณกล่าวถึงว่าเป็นรีจิสทรีนักเทียบท่าส่วนตัวดังนั้นคุณอาจต้องตรวจสอบRegistry APIแทนHub API APIของHubซึ่งเป็นลิงก์ที่คุณให้
ปัญหาที่ 2
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เพื่อตรวจสอบว่ามีอยู่ในรีจิสตรี Docker ส่วนตัวของคุณ
$ 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"}
registry
ภาพมาตรฐาน SSH ในการเรียกใช้สคริปต์ทำงานแม้ว่ามันจะไม่เหมาะก็ตาม ในฐานะที่เป็นบันทึกด้านข้างฉันยังคงคิดว่ามันเป็น API ที่ไม่สมบูรณ์ - คุณสามารถลบแท็กได้ แต่ถ้าคุณได้รับ/images
คุณยังคงเห็นข้อมูลภาพที่เหลือทั้งหมด
มันน่าเกลียดจริงๆ แต่ใช้งานได้มีการทดสอบข้อความในรีจิสตรี: 2.5.1 ฉันไม่ได้จัดการเพื่อให้การลบทำงานอย่างราบรื่นแม้หลังจากอัปเดตการกำหนดค่าเพื่อเปิดใช้งานการลบ ID เป็นเรื่องยากที่จะดึงออกมาได้ต้องลงชื่อเข้าใช้เพื่อรับมันอาจจะมีบางคนเข้าใจผิด อย่างไรก็ตามงานดังต่อไปนี้:
ล็อกอินเข้าสู่คอนเทนเนอร์
docker exec -it registry sh
กำหนดตัวแปรที่ตรงกับคอนเทนเนอร์และเวอร์ชันคอนเทนเนอร์ของคุณ:
export NAME="google/cadvisor"
export VERSION="v0.24.1"
ย้ายไปยังไดเรกทอรีรีจิสตรี:
cd /var/lib/registry/docker/registry/v2
ลบไฟล์ที่เกี่ยวข้องกับแฮชของคุณ:
find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
ลบรายการ:
rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
ออกจากระบบ
exit
เรียกใช้ GC:
docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml
หากทุกอย่างถูกต้องทำข้อมูลบางอย่างเกี่ยวกับการลบ blobs จะปรากฏขึ้น
มีลูกค้าบางคน (ใน 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
UPDATE : นี่คือการแนะนำสั้น ๆเกี่ยวกับ deckschrubber
deckschrubber
ค่อนข้างดี - ติดตั้งง่าย (ไบนารีตัวเดียว) และให้คุณลบภาพตามชื่อ (ตรงกับ regex) ตลอดจนอายุ
ERRO[0000] Could not delete image! repo=.... tag=latest
: /
สั้น ๆ ;
1) คุณต้องพิมพ์คำสั่งต่อไปนี้สำหรับ RepoDigests ของ repo นักเทียบท่า;
## 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 สำหรับการขอให้ประสบความสำเร็จ
3-) เรียกใช้ตัวเก็บรวบรวมขยะ
docker exec registry bin/registry garbage-collect --dry-run /etc/docker/registry/config.yml
registry - ชื่อคอนเทนเนอร์รีจิสตรี
สำหรับคำอธิบายรายละเอียดเพิ่มเติมป้อนคำอธิบายลิงก์ที่นี่
อิมเมจนักเทียบท่านี้มีสคริปต์ทุบตีที่สามารถใช้เพื่อลบภาพออกจากรีจิสตรี 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 $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
หลังจากการวิ่งครั้งนี้
docker exec $(docker ps | grep registry | awk '{print $1}') /bin/registry garbage-collect /etc/docker/registry/config.yml
สคริปต์ทับทิมง่ายขึ้นอยู่กับนี้คำตอบ: registry_cleaner
คุณสามารถเรียกใช้บนเครื่องท้องถิ่น:
./registry_cleaner.rb --host=https://registry.exmpl.com --repository=name --tags_count=4
และจากนั้นบนเครื่องรีจิสทรีลบ Blobs /bin/registry garbage-collect /etc/docker/registry/config.yml
กับ
นี่คือสคริปต์ตามคำตอบของ Yavuz Sert มันจะลบแท็กทั้งหมดที่ไม่ใช่เวอร์ชันล่าสุดและแท็กของพวกเขามากกว่า 950
#!/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