skip to Main Content

I need a list of all repository tags for a remote Docker registry, along with their date = the date the image tag was pushed.

Or at least the tags sorted according when they were created (without the date, but in chronological order).

What I have now (from the Official Docker docs) is:

curl -XGET -u my_user:my_pass 'https://my_registry.com/v2/my_repo/tags/list'

But that seems to return the tags in random order. I need to further filter / postprocess the tags programmatically, so I need to fetch additional per-tag metadata.

Any idea how to do that?

3

Answers


  1. In the past, I wrote a script to migrate images from local docker registry to ECR, maybe you want to use some of the lines like,

    tags=$(curl -s https://$username:$password@$privreg/v2/$repo/tags/list?n=2048 | jq '.tags[]' | tr -d '"')

    creationdate=$(curl -s https://$username:$password@$privreg/v2/$repo/manifests/$tag | jq -r '.history[].v1Compatibility' | jq '.created' | sort | tail -n1)

    #!/bin/bash
    read -p 'Username: ' username
    read -sp 'Password: ' password
    privreg="privreg.example.com"
    awsreg="<account_id>.dkr.ecr.<region_code>.amazonaws.com"
    repos=$(curl -s https://$username:$password@$privreg/v2/_catalog?n=2048 | jq '.repositories[]' | tr -d '"')
    for repo in $repos; do
        tags=$(curl -s https://$username:$password@$privreg/v2/$repo/tags/list?n=2048 | jq '.tags[]' | tr -d '"')
        project=${repo%/*}
        service=${repo#*/}
        awsrepo=$(aws ecr describe-repositories | grep -o "$repo" | tr -d '"')
        if [ "$awsrepo" != "$repo" ]; then aws ecr create-repository --repository-name $repo; fi
            for tag in $tags; do
                creationdate=$(curl -s https://$username:$password@$privreg/v2/$repo/manifests/$tag | jq -r '.history[].v1Compatibility' | jq '.created' | sort | tail -n1)
                echo "$repo:$tag      $creationdate" >> $project-$service.txt
            done
            sort -k2 $project-$service.txt | tail -n3 | cut -d " " -f1  > $project-$service-new.txt
                cat $project-$service-new.txt
            while read repoandtags; do
               sudo docker pull $privreg/$repoandtags
                   sudo docker tag  $privreg/$repoandtags $awsreg/$repoandtags
                   sudo docker push $awsreg/$repoandtags
            done < $project-$service-new.txt
    

    Script might not work and need some changes, but you can use some parts of it, so I will leave it in the post as an example.

    Login or Signup to reply.
  2. My two cents:

    order_tags_by_date() {
        if [ -z $1 ] || [ -z $2 ]; then
            echo "Get tag list of a component and order by date. Please enter a component name and a tag "
            echo "For example: tags my-app 20200606"
            return 1
        fi
        # get all tags list
        url=some_host
        result=$(curl -s $url:5000/v2/$1/tags/list)
        # parse page and get "tags" array, sort by name, reverse, and get as a tab separated values; 
        # separate with space and put into an array in bash; 
        # "reverse" to get the latest tag first; if you want old tag first, remove it
        IFS=" " read -r -a tags <<< "$(echo $result | jq -r '.tags | sort | reverse | @tsv')"
    
        # for each tag, get the same component in docker api the manifest, 
        # parse the created field by the first element in history; I assume all histories has the same created timestamp
        json="["
        for tag in $tags
        do
            host=another-docker-api-host
            date=$(curl -sk $host/v2/$1/manifests/$tag | jq -r ".history[0].v1Compatibility" | jq ".created")
            json+='{"tag":"'$tag'", "date":'$date"},"
        done;
        valid_json=${json::-1}']'
        echo $valid_json | jq 'sort_by(.date, .tag) | reverse'
    }
    

    I constructed another JSON for jq to sort on the date, tag field; because in my case, some image has timestamp based tags, but creation date is always 19700101; while other images have correct date but tags are number based; so I order by both. You can also remove "reverse" at the end to sort asc.

    If you don’t want the date, add this on the last line of the script, after reverse:

    | .[] | .tag
    

    So it will get all elements’ tag value and they are already sorted.

    jib created images, though, will have date of 1970-01-01, this is by design.

    Login or Signup to reply.
  3. The tag list should be returned using lexical ordering according to the OCI spec:

    If the list is not empty, the tags MUST be in lexical order (i.e. case-insensitive alphanumeric order).

    There’s no API presently available in OCI to query when the image was pushed. However, images do include a configuration that you can query and parse to extract the image creation time as reported by the build tooling. This date may be a lie, I’ve worked on tooling that backdates this for purposes of reproducibility (some well known date like 1970-01-01, or the datestamp of the Git commit being built), some manifests pushed may have an empty config (especially when it’s not actually an image), and a manifest list will have multiple manifests each with different configs.

    So with that disclaimer that this is very error prone, you can fetch that config blob and extract the creation date. I prefer to use tooling for this beyond curl to handle:

    • different types of authentication, or anonymous logins, that registries require
    • different types of image manifests, which I’m aware of at least 6 different manifests, OCI and Docker for images and manifest list and schema v1 manifests with and without a siganture
    • selecting a platform from multi-platform manifests and parsing the json of the config blob

    The tooling I work on for this is regclient, but there’s also crane and skopeo. With regclient/regctl, this looks like:

    repo=registry.example.com/your/repo
    regctl tag ls "$repo" | while read tag; do
      regctl image config "$repo:$tag" --format "{{ printf "%s: $tag\n" .Created }}"
    done
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search