Docker pull image, match tag by regex/wildcard

573 Views Asked by At

I'm using an image that sometimes has a rolling version change (namespace/repo:...-1 -> -2) and they also delete the old version. I am trying to pull their image but a regex doesn't work. I tried docker pull namespace/repo:....-* and so on. Is there any way to pull a docker image using a regex/wildcard or fetch the latest rolling version?

2

There are 2 best solutions below

0
BMitch On

This is not a capability of docker pull or any of the other container runtimes that I'm aware of. The typical process used by the image publisher is to publish multiple tags, e.g. namespace/repo:v1.2.3-4, namespace/repo:v1.2.3, namespace/repo:v1.2, and namespace/repo:v1 that all point to the same underlying manifest. Then when the -5 is released, the less specific tags are also updated and users pick what level of granularity they require in the tag name they use.

The other option is to used a tool that can lists tags in a repository. That API is part of the OCI distribution-spec implemented by most container registries. Various client side tools expose this API, in particular Google's crane, RedHat's skopeo, and my own regclient each implement the tag listing query. From there, you script that output to grep, e.g.:

$ regctl tag ls golang | egrep '1\.21\..*-alpine$'
1.21.0-alpine

You'd then want to do a semver sort on output like the above, or a numeric sort on a single part of the version.

0
larsks On

Expanding on my comment, interacting with the Docker Hub API directly you could use something like this:

#!/bin/bash

[[ $1 =~ (([^/]*)/)?([^:]*)(:(.*))? ]]

repo=${BASH_REMATCH[2]}
image=${BASH_REMATCH[3]}
tag=${BASH_REMATCH[5]}

found_tag=$(
    curl -sSf \
    "https://hub.docker.com/v2/namespaces/${repo:-library}/repositories/${image}/tags?page_size=100" |
    jq -r '.results|sort_by(.last_updated)[]|.name' |
    tee sorted |
    grep "${tag:-.}" |
    tail -1
)

if [[ -z $found_tag ]]; then
    echo "ERROR: no matching tags" >&2
    exit 1
fi

echo "${repo:+$repo/}$image:$found_tag"

This will return the most recent (by date last updated) tag matching a regular expression. Assuming we have named this script get-latest-matching, we would see:

$ get-latest-matching golang
golang:latest
$ get-latest-matching golang:1.21
golang:1.21.0-bullseye
$ get-latest-matching golang:1.21\$
golang:1.21
$ get-latest-matching golang:1.21.\*alpine
golang:1.21.0-alpine3.18
$ get-latest-matching golang:1.21.\*alpine\$
golang:1.21.0-alpine

It works just as well with non-library images:

$ get-latest-matching netboxcommunity/netbox
netboxcommunity/netbox:snapshot-2.6.1
$ bash get-latest-matching netboxcommunity/netbox:v3
netboxcommunity/netbox:v3.5-2.6.1