├── Dockerfile ├── README.md └── delete_image.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.6 2 | 3 | ENV KUBE_LATEST_VERSION="v1.10.0" 4 | 5 | RUN apk add --update ca-certificates \ 6 | && apk add --update curl \ 7 | && apk add --update gettext \ 8 | && apk add --update bash \ 9 | && curl -L https://storage.googleapis.com/kubernetes-release/release/${KUBE_LATEST_VERSION}/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl \ 10 | && chmod +x /usr/local/bin/kubectl \ 11 | && rm /var/cache/apk/* 12 | 13 | ADD delete_image.sh /delete_image.sh 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gitlab registry cleaner 2 | 3 | Out of the box, there is no easy way to delete a special tag of a given image in the Gitlab registry (as of version 10.8). 4 | 5 | This image provides a simple script that enables you to delete images easily. 6 | 7 | --- 8 | 📌 **Deprecation Notice** 9 | 10 | This repository is deprecated and no more work will be done on this by The Coding Machine. You can use instead [reg tool](https://docs.gitlab.com/ee/user/packages/container_registry/#delete-images-using-gitlab-cicd) or [gitlab api](https://docs.gitlab.com/ee/api/container_registry.html#delete-a-registry-repository-tag) for same usage. 11 | 12 | --- 13 | 14 | 15 | ## Why? 16 | 17 | If you want to do continuous deployment, it is not uncommon to build one image per pipeline in Gitlab. You will typically 18 | tag all your images using the commit SHA or the branch name. You will soon end up having a lot of images in your Gitlab 19 | registry. Docker images are big, and disk-space is finite so at some point, you will need to have a mechanism to 20 | automatically delete an image when it is no more needed. 21 | 22 | As it turns out, deleting an image is surprisingly difficult, due to a number of outstanding issues: 23 | 24 | - [#20176 - Provide a programmatic method to delete images/tags from the registry](https://gitlab.com/gitlab-org/gitlab-ce/issues/20176) 25 | - [#21608 - Container Registry API](https://gitlab.com/gitlab-org/gitlab-ce/issues/21608) 26 | - [#25322 - Create a mechanism to clean up old container image revisions](https://gitlab.com/gitlab-org/gitlab-ce/issues/25322) 27 | - [#28970 - Delete from registry images for merged branches](https://gitlab.com/gitlab-org/gitlab-ce/issues/28970) 28 | - [#39490 - Allow to bulk delete docker images](https://gitlab.com/gitlab-org/gitlab-ce/issues/39490) 29 | - [#40096 - pipeline user $CI_REGISTRY_USER lacks permission to delete its own images](https://gitlab.com/gitlab-org/gitlab-ce/issues/40096) 30 | 31 | This image is here to help. 32 | 33 | ## Usage 34 | 35 | You will typically use this image in your `.gitlab-ci.yml` file. 36 | 37 | **.gitlab-ci.yml** 38 | ```yml 39 | delete_image: 40 | stage: cleanup 41 | image: thecodingmachine/gitlab-registry-cleaner:latest 42 | script: 43 | - /delete_image.sh registry.gitlab.mycompany.com/path/to/image:$CI_COMMIT_REF_NAME 44 | when: manual 45 | environment: 46 | name: review/$CI_COMMIT_REF_NAME 47 | action: stop 48 | only: 49 | - branches 50 | except: 51 | - master 52 | ``` 53 | 54 | The `/delete_image.sh` script takes one single argument: the full path to the image to be deleted (including the tag). 55 | 56 | **Important**: for the script to work, you must add a "Secret variable" in Gitlab CI named `CI_ACCOUNT`. 57 | This variable must be in the form `[user]:[password]` where [user] is a Gitlab user that has access to the registry 58 | and [password] is the Gitlab password of the user. This can be regarded obviously as a security issue if you don't trust 59 | all developers who have access to the CI environment (as they will be able to "echo" this secret variable). 60 | 61 | This is needed because the default Gitlab registry token available to the CI does not have the rights to delete 62 | an image by default. An issue is opened in Gitlab to fix this issue: [#39490 - Allow to bulk delete docker images](https://gitlab.com/gitlab-org/gitlab-ce/issues/39490) 63 | 64 | ## Special thanks 65 | 66 | All the hard work has been done by [Alessandro Lai](https://engineering.facile.it/blog/eng/continuous-deployment-from-gitlab-ci-to-k8s-using-docker-in-docker/#the-scary-part-deleting-docker-images) 67 | and [Vincent Composieux](https://gitlab.com/gitlab-org/gitlab-ce/issues/21608#note_53674456). 68 | 69 | I've only put your ideas in a Docker image. 70 | 71 | ## Miscellaneous 72 | 73 | This image also contains `kubectl` (the command line tool for Kubernetes) that can be useful to perform cleanup actions 74 | in a Kubernetes cluster. 75 | -------------------------------------------------------------------------------- /delete_image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Cleanup image from Gitlab registry. First parameter must be the full path to the iamge to be removed. 4 | 5 | set -e 6 | 7 | #set -x 8 | 9 | URL=$1 10 | LASTPART=${URL#*/} 11 | TAG=${LASTPART#*:} 12 | #REGISTRY_URL=${URL%%/*} 13 | PROJECT=${LASTPART%%:*} 14 | 15 | # Check parameter passed starts with REGISTRY_URL 16 | [[ ! $1 == $CI_REGISTRY_IMAGE* ]] && echo "The image full path should start with $CI_REGISTRY_IMAGE" && exit 1 17 | 18 | [ -z "$CI_ACCOUNT" ] && echo "You need to set the CI_ACCOUNT environment variable to '[user]:[password]' where user is a valid Gitlab user that has access to the Gitlab image you want to delete." && exit 1; 19 | 20 | GITLAB_URL=$(echo $CI_PROJECT_URL | awk -F/ '{print $1"//"$3}') 21 | 22 | # Authenticates with Gitlab Registry 23 | # CI_ACCOUNT env var should contain "login:password" of a user that has access to repository 24 | TOKEN=$(curl -s -u "$CI_ACCOUNT" "${GITLAB_URL}/jwt/auth?client_id=docker&offline_token=true&service=container_registry&scope=repository:${PROJECT}:pull,*" | sed -r "s/(\{\"token\":\"|\"\})//g") 25 | #echo $TOKEN 26 | 27 | # Obtain digest from tag name 28 | #- echo curl -sI -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer $TOKEN" https://${CI_REGISTRY}/v2/${CI_PROJECT_PATH}/manifests/$CI_COMMIT_REF_SLUG | grep -Fi Docker-Content-Digest | sed -e 's/Docker-Content-Digest: //' -e 's/\:/\\:/' 29 | DIGEST=$(curl -sI -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer $TOKEN" https://${CI_REGISTRY}/v2/${PROJECT}/manifests/$TAG | grep -Fi Docker-Content-Digest | sed -e "s/Docker-Content-Digest: //" -e "s/\:/\\:/" | sed 's/\r$//') 30 | 31 | # Removes pipeline-built Docker image from Gitlab's registry 32 | curl -X DELETE -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "Authorization: Bearer $TOKEN" https://${CI_REGISTRY}/v2/${PROJECT}/manifests/$DIGEST 33 | --------------------------------------------------------------------------------