-
Notifications
You must be signed in to change notification settings - Fork 806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
skopeo delete - multiarch image oci v1 not fully deleted (artifactory) #2497
Comments
Thanks for reaching out. In general, explicitly deleting the components is not safe, because those manifests may well be referenced from other images, or from other tags (and deleting a manifest by digest, the way |
Unfortunately
Example script: #!/bin/bash
set -euo pipefail
# Requires jf cli, jq, parallel and skopeo
export ART_HOSTNAME='artifactory.example.com'
main(){
garbage_collect_dandling_images "my-art-repo-1"
garbage_collect_dandling_images "my-art-repo-2"
# ...
}
# $1: artifactory repository name
garbage_collect_dandling_images(){
local repo="${1}"
local query_aql_all_images=; query_aql_all_images=$(cat <<EOF
items.find({
"repo": "${repo}",
"modified": {"\$before": "10minutes"},
"\$and": [
{"name": {"\$eq": "manifest.json"}},
{"path": {"\$match": "*/sha256:*"}}
],
"type": "file"
}).include("repo", "path", "name", "created", "modified")
EOF
)
local query_aql_all_indexes=; query_aql_all_indexes=$(cat <<EOF
items.find({
"repo": "${repo}",
"\$and": [
{"name": {"\$eq": "list.manifest.json"}}
],
"type": "file"
}).include("repo", "path", "name", "created", "modified")
EOF
)
# First fetch each images to avoid race condition creation vs deletion (sha256:.* folders only) + added a fixed duration for extra safety
local images_to_process=;images_to_process="$(jf rt curl -X POST /api/search/aql -H "Content-Type: text/plain" -d "${query_aql_all_images}" | jq -r '.results[] | "\(.path)"')"
log_info "Found $(echo "${images_to_process}" |wc -l) images to process in ${1}"
local index_files=;index_files="$(jf rt curl -X POST /api/search/aql -H "Content-Type: text/plain" -d "${query_aql_all_indexes}" | jq -r '.results[] | "\(.path)/\(.name)"')"
log_info "Found $(echo "${index_files}" |wc -l) list.manifest.json in ${1}"
log_info "Fetching all digests images from all list.manifest.json files."
echo "${index_files}" | parallel --halt now,fail=1 -kj 9 "jf rt 2>/dev/null curl \"${1}/{}\" | jq -r '.manifests[] | .digest'" > /tmp/images_to_keep.txt
log_info "Processing images..."
local nb_deleted=0
while IFS= read -r image; do
# TODO optimize with parallel requests if too slow...
image="${image%/*}@${image##*/}"
if grep -Fxq "${image##*@}" /tmp/images_to_keep.txt; then
echo " Keep image still referenced ${image}"
else
echo " Delete dandling image ${image}"
delete_image "${ART_HOSTNAME}/${repo}/${image}"
nb_deleted=$((nb_deleted+1))
fi
done <<< "${images_to_process}"
log_info "Garbage collection done for ${1}\n Deleted ${nb_deleted} images of $(echo "${images_to_process}" |wc -l) images."
}
# $1: Image ref to delete
# One does not simply delete a tag without deleting all tags associated with the same manifest...
# You may want to use regctl to delete a tag without deleting the manifest and all tags associated with it.
# - https://flightaware.engineering/how-hard-is-it-to-delete-a-docker-tag/
# - https://stackoverflow.com/questions/71576754/delete-tags-from-a-private-docker-registry
delete_image(){
if [ "${DRY_RUN}" = 'false' ]; then
skopeo delete "docker://${1}" || log_warn "Image could not be deleted or does not exist. ${1}"
fi
}
main "$@" |
skopeo delete
doesn't fully delete oci v1 multiarch images. (at least on artifactory )It just deletes the "index"
list.manifest.json
but won't delete any of the referenced manifests corresponding to each architecture & attestation.Thus the associated layers will never be deleted because they are still referenced by an existing manifest.
In other terms it (almost) don't free any disk space. (a warning in the man page would be nice)
Maybe this issue should be at container/image, let me know.
Any inputs welcomed.
Example
list.manifest.json
of taglatest
:Manifest.json of
sha256:bafedd5...
Before deletion of tag
latest
After deletion of
latest
withskopeo delete docker://..../my-image:latest
, the two linked manifests still exists:Still possible to delete the sub manifests manually with
skopeo delete docker://.../my-image@sha256:bafedd65..
:resources:
The text was updated successfully, but these errors were encountered: