Given a tag `latest`, we want to find out another tag with the same image ID on Docker Hub.
Here is how to find out all tags for a repo with the Docker Hub API v2:
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)
curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/fluent/fluentd/tags/?page_size=100 | jq
(See gist.github.com/kizbitz)
Unfortunately, it doesn't contain the image ID but always a `null` value for this key:
$ curl -s -H "Authorization: JWT ${TOKEN}" https://hub.docker.com/v2/repositories/fluent/fluentd/tags/?page_size=100 | jq
{
"count": 36,
"next": null,
"previous": null,
"results": [
...
{
"name": "v0.14.11",
"full_size": 11964464,
"id": 7084687,
"repository": 219785,
"creator": 2923,
"last_updater": 2923,
"last_updated": "2016-12-27T07:16:41.294807Z",
"image_id": null,
"v2": true,
"platforms": [
5
]
},
...
Unfortunately, the image ID is something different than the `id` in the JSON above.
$ docker images | grep fluent
docker.io/fluent/fluentd v0.14.11 1441d57beff9 3 weeks ago 38.25 MB
Theoretically, it should be possible to access the Docker Manifests and along with the the image ID with this Docker Registry call but it doesn't help either:
$ curl -s -H "Authorization: JWT ${TOKEN}" "https://registry.hub.docker.com/v2/fluent/fluentd/manifests/latest"
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Name":"fluent/fluentd","Action":"pull"}]}]}
(See stackoverflow.com)
Here is a similar issue in the Docker GitHub repo but I still cannot figure out the solution: https://github.com/docker/distribution/issues/1490 .
P.S.: Here is my Docker version with which I tried to push a test image:
$ docker version
Client:
Version: 1.12.6
API version: 1.24
Package version: docker-common-1.12.6-5.git037a2f5.fc25.x86_64
Go version: go1.7.4
Git commit: 037a2f5/1.12.6
Built: Wed Jan 18 12:11:29 2017
OS/Arch: linux/amd64
Docker Registry API v2 uses image digest instead of image ID to distinguish image identity.
The image digest can be obtained from Docker-Content-Digest of the HTTP response header by making the following API call:
$ REPOSITORY=fluent/fluentd
$ TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$REPOSITORY:pull" | jq -r .token)
$ curl -s -D - -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://index.docker.io/v2/$REPOSITORY/manifests/latest
HTTP/1.1 200 OK
Content-Length: 1982
Content-Type: application/vnd.docker.distribution.manifest.v2+json
Docker-Content-Digest: sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db
Docker-Distribution-Api-Version: registry/2.0
Etag: "sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db"
Date: Tue, 24 Jan 2017 13:34:53 GMT
Strict-Transport-Security: max-age=31536000
...
All tags can be obtained with the following API call:
$ curl -s -H "Authorization: Bearer $TOKEN" https://index.docker.io/v2/$REPOSITORY/tags/list
{"name":"fluent/fluentd","tags":["edge-onbuild","edge","jemalloc","latest-onbuild","latest","onbuild","stable-onbuild","stable","ubuntu-base","v0.12-latest-onbuild","v0.12-latest","v0.12-onbuild","v0.12.16","v0.12.18","v0.12.19","v0.12.20","v0.12.21","v0.12.23","v0.12.24","v0.12.26-2","v0.12.26-onbuild","v0.12.26","v0.12.27-onbuild","v0.12.27","v0.12.28-onbuild","v0.12.28","v0.12.29-onbuild","v0.12.29","v0.12.30-onbuild","v0.12.30","v0.12.31-onbuild","v0.12.31","v0.12","v0.14-latest-onbuild","v0.14-latest","v0.14-onbuild","v0.14.1","v0.14.10-onbuild","v0.14.10","v0.14.11-onbuild","v0.14.11","v0.14.2","v0.14.6","v0.14.8","v0.14"]}
Based on the above, to find the same digest as a specific tag, it will be a script like the following.
#!/bin/bash
REPOSITORY=$1
TARGET_TAG=$2
# get authorization token
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$REPOSITORY:pull" | jq -r .token)
# find all tags
ALL_TAGS=$(curl -s -H "Authorization: Bearer $TOKEN" https://index.docker.io/v2/$REPOSITORY/tags/list | jq -r .tags[])
# get image digest for target
TARGET_DIGEST=$(curl -s -D - -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://index.docker.io/v2/$REPOSITORY/manifests/$TARGET_TAG | grep Docker-Content-Digest | cut -d ' ' -f 2)
# for each tags
for tag in ${ALL_TAGS[#]}; do
# get image digest
digest=$(curl -s -D - -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://index.docker.io/v2/$REPOSITORY/manifests/$tag | grep Docker-Content-Digest | cut -d ' ' -f 2)
# check digest
if [[ $TARGET_DIGEST = $digest ]]; then
echo "$tag $digest"
fi
done
The result is as follows:
$ ./find_same_digest.sh fluent/fluentd latest
latest sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db
stable sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db
v0.12.31 sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db
v0.12 sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db
If you want to check the digest of the local image, you can get it with docker images --digests:
$ docker images --digests | grep fluentd
fluent/fluentd latest sha256:eaea1edffc34cff3b5e31ee738ea56e46326f90731b4139a19948814a4f0a4db 1788ee7dcfcc 14 hours ago 35.41 MB
The above answer is great! In addition, if you want to use this on a private repo, you need to add basic auth with your registry user credentials, and the additional scope parameter 'account='
(see http://www.cakesolutions.net/teamblogs/docker-registry-api-calls-as-an-authenticated-user)
Similar to the question "What´s the sha256 code of a docker image?", I would like to find the digest of a Docker image. I can see the digest when I download an image:
$ docker pull waisbrot/wait:latest
latest: Pulling from waisbrot/wait
Digest: sha256:6f2185daa4ab1711181c30d03f565508e8e978ebd0f263030e7de98deee5f330
Status: Image is up to date for waisbrot/wait:latest
$
Another question, What is the Docker registry v2 API endpoint to get the digest for an image has an answer suggesting the Docker-Content-Digest header.
I can see that there is a Docker-Content-Digest header when I fetch the manifest for the image:
$ curl 'https://auth.docker.io/token?service=registry.docker.io&scope=repository:waisbrot/wait:pull' -H "Authorization: Basic ${username_password_base64}"
# store the resulting token in DT
$ curl -v https://registry-1.docker.io/v2/waisbrot/wait/manifests/latest -H "Authorization: Bearer $DT" -XHEAD
* Trying 52.7.141.30...
* Connected to registry-1.docker.io (52.7.141.30) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.docker.io
* Server certificate: RapidSSL SHA256 CA - G3
* Server certificate: GeoTrust Global CA
> GET /v2/waisbrot/wait/manifests/latest HTTP/1.1
> Host: registry-1.docker.io
> User-Agent: curl/7.43.0
> Accept: */*
> Authorization: Bearer LtVRw-etc-etc-etc
>
< HTTP/1.1 200 OK
< Content-Length: 4974
< Content-Type: application/vnd.docker.distribution.manifest.v1+prettyjws
< Docker-Content-Digest: sha256:128c6e3534b842a2eec139999b8ce8aa9a2af9907e2b9269550809d18cd832a3
< Docker-Distribution-Api-Version: registry/2.0
< Etag: "sha256:128c6e3534b842a2eec139999b8ce8aa9a2af9907e2b9269550809d18cd832a3"
< Date: Wed, 07 Sep 2016 16:37:15 GMT
< Strict-Transport-Security: max-age=31536000
However, this header isn't the same. The pull command got me 6f21 and the header shows 128c. Further, the pull command doesn't work for that digest:
$ docker pull waisbrot/wait#sha256:128c6e3534b842a2eec139999b8ce8aa9a2af9907e2b9269550809d18cd832a3
Error response from daemon: manifest unknown: manifest unknown
whereas things work as I want when I have the correct digest:
$ docker pull waisbrot/wait#sha256:6f2185daa4ab1711181c30d03f565508e8e978ebd0f263030e7de98deee5f330 12:46 waisbrot#influenza
sha256:6f2185daa4ab1711181c30d03f565508e8e978ebd0f263030e7de98deee5f330: Pulling from waisbrot/wait
Digest: sha256:6f2185daa4ab1711181c30d03f565508e8e978ebd0f263030e7de98deee5f330
Status: Image is up to date for waisbrot/wait#sha256:6f2185daa4ab1711181c30d03f565508e8e978ebd0f263030e7de98deee5f330
What I'm looking for is a way to translate the latest tag (which changes all the time) into a fixed digest that I can reliably pull. But I don't want to actually pull it down in order to do this translation.
edit 2022-10-04:
# INPUT
REPO=waisbrot/wait
user=my-user
password=my-password
# Get TOKEN
username_password_base64=$(echo -n $user:$password | base64)
TOKEN=$(curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
-H "Authorization: Basic ${username_password_base64}" \
'https://auth.docker.io/token?service=registry.docker.io&scope=repository:waisbrot/wait:pull' \
| jq -r .token)
# GET Digest from v2 API
curl -s -D - -H "Authorization: Bearer $TOKEN" \
https://registry-1.docker.io/v2/waisbrot/wait/manifests/latest 2>&1 \
| grep docker-content-digest \
| cut -d' ' -f2
original answer:
For newer versions of Docker, the inspect command provides the correct value (requires the image to have been pulled as Jan Hudec has pointed out in the comments):
docker inspect --format='{{index .RepoDigests 0}}' waisbrot/wait
For older versions, fetch the value from the repository following this example with the main Docker repo:
curl -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
-H "Authorization: Basic ${username_password_base64}" \
'https://auth.docker.io/token?service=registry.docker.io&scope=repository:waisbrot/wait:pull'
Naive attempts to fetch that value fail because the default content-type being selected by the server is application/vnd.docker.distribution.manifest.v1+prettyjws (a v1 manifest) and you need to v2 manifest. Therefore, you need to set the Accept header to application/vnd.docker.distribution.manifest.v2+json.
This is how you do it today using a V2 manifest.
docker manifest inspect <REMOTE IMAGE>:<TAG> -v
Your output is JSON:
{
...
"Descriptor": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"digest": "sha256:d13e102941a9f7bd417440f62f9cb29de35f6acb13a26cbf6a34f4c7340f0b63",
"size": 3255,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
...
}
With 2 http requests, you can get it. The first one to get an authentication token, and the second to get the image digest list by architecture and variant:
token=$(curl --silent "https://auth.docker.io/token?scope=repository:$image:pull&service=registry.docker.io" | jq -r '.token')
curl -s --header "Accept: application/vnd.docker.distribution.manifest.list.v2+json" --header "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/$image/manifests/$tag" | jq -r '.manifests|.[]| "\(.digest) \(.platform.architecture) \(.platform.variant)"'
Example with:
image=library/nginx
tag=stable-alpine
sha256:8853c7e938c2aa5d9d7439e698f0e700f058df8414a83134a09fcbb68bb0707a amd64 null
sha256:dbcd23f95b94018fe72bfdb356e40f4ae8b95063883f3456fedaed1c02204ed4 arm v6
sha256:d3670edcd50bb07cae303767426adf9bc7ba0219736148d30e6f30dd4e08695c arm v7
sha256:0bcd76faa141e4fa37e875834b3994261e0cfc94b7233ac84896381315b845ca arm64 v8
sha256:da8e62ddb3fab89ff4fa0271dbe230f849ab53402a71338503952437dcda1026 386 null
sha256:269bf99e100294b6b75fbdecf7b4ddbef8b29ea0a953e2e904452a50dbc923ab ppc64le null
sha256:103da50956034c157abeffbc869e2e38a4fabbf913bed8ae6ae7c59e646b28a1 s390x null
I encountered a task recently that required viewing the sha256 digest without necessarily pulling the image. The tool skopeo makes the registry API calls so you don't need to pull the image.
For example,
$ skopeo inspect --creds "username:password" docker://waisbrot/wait:latest
You could then pipe this to jq if you want to get just the digest value.
$ skopeo inspect --creds "username:password" \
docker://waisbrot/wait:latest | jq -r '.Digest'
sha256:6f2185daa4ab1711181c30d03f565508e8e978ebd0f263030e7de98deee5f330
I realise this issue is answered however either I am missing something or the current version of AWS ECR registry service does not work as expected.
When trying to get the digest from AWS ECR using either HEAD and also trying to switch the content-type does not return a digest value that I can use to pull an image using the registry Api.
To get this digest you have to get the manifest for the tag you are interested in and calculate the sha256 of the response Json as is, including the formatting, without the signature section
I struggled with this also. Here is a C# (dotnet core 5.0) implementation if anyone is intersted:
/**
TOKEN=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:waisbrot/wait:pull" | jq -r .token)
curl -s -D - -H "Authorization: Bearer $TOKEN" -H "Accept: application/vnd.docker.distribution.manifest.v2+json" https://index.docker.io/v2/waisbrot/wait/manifests/latest
*/
private string GetRemoteImageDigest(string image, string tag) {
using HttpClient client = new ();
var url = string.Format($"https://auth.docker.io/token?service=registry.docker.io&scope=repository:{image}:pull");
//var response = client.Send(new HttpRequestMessage(HttpMethod.Get, url));
var result = client.GetStringAsync(url);
var drt = JsonSerializer.Deserialize<DockerRegistryToken>(result.Result);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", drt.Token);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.docker.distribution.manifest.v2+json"));
var response = client.GetAsync(string.Format($"https://index.docker.io/v2/{image}/manifests/{tag}"));
var headers = response.Result.Headers;
IEnumerable<string> values;
headers.TryGetValues("Docker-Content-Digest", out values);
return values.FirstOrDefault();
}
DockerRegistryToken is defined as:
public class DockerRegistryToken{
[JsonPropertyName("token")]
public string Token { get; set; }
/// always null
[JsonPropertyName("access_token")]
public string AccessToken {get; set; }
[JsonPropertyName("expires_in")]
public int ExpiresInSeconds { get; set; }
[JsonPropertyName("issued_at")]
public DateTime IssuedAt { get; set; }
}
As mentioned in other answers, this digest did not match because you attempted to curl without an Accept header, and so the registry triggered a fallback to an older v1 image manifest:
< Content-Type: application/vnd.docker.distribution.manifest.v1+prettyjws
< Docker-Content-Digest: sha256:128c6e3534b842a2eec139999b8ce8aa9a2af9907e2b9269550809d18cd832a3
You can query Hub with curl using a script like:
#!/bin/sh
ref="${1:-library/ubuntu:latest}"
sha="${ref#*#}"
if [ "$sha" = "$ref" ]; then
sha=""
fi
wosha="${ref%%#*}"
repo="${wosha%:*}"
tag="${wosha##*:}"
if [ "$tag" = "$wosha" ]; then
tag="latest"
fi
cto="application/vnd.oci.image.index.v1+json"
ctol="application/vnd.oci.image.manifest.v1+json"
ctd="application/vnd.docker.distribution.manifest.v2+json"
ctdl="application/vnd.docker.distribution.manifest.list.v2+json"
token=$(curl -sL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${repo}:pull" \
| jq -r '.token')
curl -H "Accept: ${cto}" -H "Accept: ${ctol}" -H "Accept: ${ctd}" -H "Accept: ${ctdl}" \
-H "Authorization: Bearer $token" \
-I -sL "https://registry-1.docker.io/v2/${repo}/manifests/${sha:-$tag}"
However, that's limited since it's specific to Hub, and you still need to parse the headers. From the skopeo output, it's still pulling the entire manifest rather than a HEAD request, which will count against Hub rate limits.
Instead my two preferred tools for this are go-containerregistry/crane and regclient/regctl (I'm the author of the latter). Each has a digest command which automatically handles auth to different registries, includes the needed Accept headers, and parses the output to just the digest which is useful for scripting:
$ regctl image digest busybox
sha256:3b3128d9df6bbbcc92e2358e596c9fbd722a437a62bafbc51607970e9e3b8869
$ crane digest busybox
sha256:3b3128d9df6bbbcc92e2358e596c9fbd722a437a62bafbc51607970e9e3b8869
To avoid installing other tools, docker now has docker buildx imagetools inspect, but similar to skopeo, this is pulling the entire manifest rather than a HEAD request:
$ docker buildx imagetools inspect busybox
Name: docker.io/library/busybox:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:3b3128d9df6bbbcc92e2358e596c9fbd722a437a62bafbc51607970e9e3b8869
...
$ docker buildx imagetools inspect busybox --format '{{json .}}' | jq -r .manifest.digest
sha256:3b3128d9df6bbbcc92e2358e596c9fbd722a437a62bafbc51607970e9e3b8869
example for reg which requires redirect (curl follow 302)
REGISTRY_ADDRESS='registry.access.redhat.com'
image='ubi8/openjdk-17-runtime'
curl --silent -L \
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"https://$REGISTRY_ADDRESS/v2/$image/manifests/latest" |
jq -r '.config.digest'
Following up on ByteFlinger's suggestion, which did not have an example, I tried this, and this is how to calculate it:
$ docker-ls tag -registry https://myregistry.net:5000
spicysomtam/zookeeper:latest
requesting manifest . done
repository: spicysomtam/zookeeper
tagName: latest
digest: sha256:bd5dd80253171e4dffccbea7c639c90a63d5424aa2d7fe655aea766405c83036
$ curl -ns -H "Accept:
application/vnd.docker.distribution.manifest.v2+json" -X GET
https://myregistry.net:5000/v2/spicysomtam/zookeeper/manifests/latest|sha256sum
bd5dd80253171e4dffccbea7c639c90a63d5424aa2d7fe655aea766405c83036 -
$ docker images --digests |grep zookeeper
myregistry.net:5000/spicysomtam/zookeeper latest sha256:bd5dd80253171e4dffccbea7c639c90a63d5424aa2d7fe655aea766405c83036 a983e71ca22d 29 hours ago 584MB
You can get this using docker inspect:
docker inspect --format='{{index .RepoDigests 0}}' ${IMAGE_NAME}
Docs: https://docs.docker.com/engine/reference/commandline/inspect/
This has been in place since at least v1.9.
How can I list all tags of a Docker image on a remote Docker registry using the CLI (preferred) or curl?
Preferably without pulling all versions from the remote registry. I just want to list the tags.
Update: sadly this solution will no longer work because Docker has deprecated the v1 API.
I got the answer from here . Thanks a lot! :)
Just one-line-script:(find all the tags of debian)
wget -q https://registry.hub.docker.com/v1/repositories/debian/tags -O - | sed -e 's/[][]//g' -e 's/"//g' -e 's/ //g' | tr '}' '\n' | awk -F: '{print $3}'
UPDATE
Thanks for #degelf's advice.
Here is the shell script.
#!/bin/bash
if [ $# -lt 1 ]
then
cat << HELP
dockertags -- list all tags for a Docker image on a remote registry.
EXAMPLE:
- list all tags for ubuntu:
dockertags ubuntu
- list all php tags containing apache:
dockertags php apache
HELP
fi
image="$1"
tags=`wget -q https://registry.hub.docker.com/v1/repositories/${image}/tags -O - | sed -e 's/[][]//g' -e 's/"//g' -e 's/ //g' | tr '}' '\n' | awk -F: '{print $3}'`
if [ -n "$2" ]
then
tags=` echo "${tags}" | grep "$2" `
fi
echo "${tags}"
You can just create a new file name, dockertags, under /usr/local/bin (or add a PATH env to your .bashrc/.zshrc), and put that code in it.
Then add the executable permissions(chmod +x dockertags).
Usage:
dockertags ubuntu ---> list all tags of ubuntu
dockertags php apache ---> list all php tags php containing 'apache'
As of Docker Registry V2, a simple GET suffice:
GET /v2/<name>/tags/list
See docs for more.
If you want to use the docker registry v2 API, it lists tags by pages. To list all the tags of an image, you may would like to add a large page_size parameter to the url, e.g.
curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/centos/tags?page_size=1024'|jq '."results"[]["name"]'
The Docker V2 API requires an OAuth bearer token with the appropriate claims. In my opinion, the official documentation is rather vague on the topic. So that others don't go through the same pain I did, I offer the below docker-tags function.
The most recent version of docker-tags can be found in my GitHubGist : "List Docker Image Tags using bash".
The docker-tags function has a dependency on jq. If you're playing with JSON, you likely already have it.
#!/usr/bin/env bash
docker-tags() {
arr=("$#")
for item in "${arr[#]}";
do
tokenUri="https://auth.docker.io/token"
data=("service=registry.docker.io" "scope=repository:$item:pull")
token="$(curl --silent --get --data-urlencode ${data[0]} --data-urlencode ${data[1]} $tokenUri | jq --raw-output '.token')"
listUri="https://registry-1.docker.io/v2/$item/tags/list"
authz="Authorization: Bearer $token"
result="$(curl --silent --get -H "Accept: application/json" -H "Authorization: Bearer $token" $listUri | jq --raw-output '.')"
echo $result
done
}
Example
docker-tags "microsoft/nanoserver" "microsoft/dotnet" "library/mongo" "library/redis"
Admittedly, docker-tags makes several assumptions. Specifically, the OAuth request parameters are mostly hard coded. A more ambitious implementation would make an unauthenticated request to the registry and derive the OAuth parameters from the unauthenticated response.
You can list all the tags with skopeo and jq for json parsing through cli.
skopeo --override-os linux inspect docker://httpd | jq '.RepoTags'
[
"2-alpine",
"2.2-alpine",
"2.2.29",
"2.2.31-alpine",
"2.2.31",
"2.2.32-alpine",
"2.2.32",
"2.2.34-alpine",
"2.2.34",
"2.2",
"2.4-alpine",
"2.4.10",
"2.4.12",
"2.4.16",
"2.4.17",
"2.4.18",
"2.4.20",
"2.4.23-alpine",
"2.4.23",
"2.4.25-alpine",
"2.4.25",
"2.4.27-alpine",
"2.4.27",
"2.4.28-alpine",
"2.4.28",
"2.4.29-alpine",
"2.4.29",
"2.4.32-alpine",
"2.4.32",
"2.4.33-alpine",
"2.4.33",
"2.4.34-alpine",
"2.4.34",
"2.4.35-alpine",
"2.4.35",
"2.4.37-alpine",
"2.4.37",
"2.4.38-alpine",
"2.4.38",
"2.4.39-alpine",
"2.4.39",
"2.4.41-alpine",
"2.4.41",
"2.4.43-alpine",
"2.4.43",
"2.4",
"2",
"alpine",
"latest"
]
For external registries:
skopeo --override-os linux inspect --creds username:password docker://<registry-url>/<repo>/<image> | jq '.RepoTags'
Note: --override-os linux is only needed if you are not running on a linux host. For example, you'll have better results with it if you are on MacOS.
If the JSON parsing tool, jq is available
wget -q https://registry.hub.docker.com/v1/repositories/debian/tags -O - | \
jq -r '.[].name'
I've managed to get it working using curl:
curl -u <username>:<password> https://myrepo.example/v1/repositories/<username>/<image_name>/tags
Note that image_name should not contain user details etc. For example if you're pushing image named myrepo.example/username/x then image_name should be x.
Building on Yan Foto's answer (the v2 api), I created a simple Python script to list the tags for a given image.
Usage:
./docker-registry-list.py alpine
Output:
{
"name": "library/alpine",
"tags": [
"2.6",
"2.7",
"3.1",
"3.2",
"3.3",
"3.4",
"3.5",
"3.6",
"3.7",
"edge",
"latest"
]
}
You can achieve by running on terminal this:
curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/mysql/tags/' | jq . | grep name
Also, if you don't have jq you have to install it by
sudo apt-get install jq
See CLI utility: https://www.npmjs.com/package/docker-browse
Allows enumeration of tags and images.
docker-browse tags <image> will list all tags for the image. e.g. docker-browse tags library/alpine
docker-browse images will list all images in the registry. Not currently available for index.docker.io.
You may connect it to any registry, including your private one, so long as it supports Docker Registry HTTP API V2
Here's a Powershell script I wrote for Windows. Handles v1 and v2 repos:
Get-DockerImageVersions.ps1:
param (
[Parameter (Mandatory=$true)]$ImageName,
[Parameter (Mandatory=$false)]$RegistryURL
)
if (!$RegistryURL)
{
$RegistryURL = "https://registry.hub.docker.com/v1/repositories"
}
$list = ""
if ($RegistryURL -like "*v2*")
{
$list = "/list"
}
$URL = "$RegistryURL/$ImageName/tags$list"
write-debug $URL
$resp = Invoke-WebRequest -UseBasicParsing $URL | ConvertFrom-Json
if ($RegistryURL -like "*v2*")
{
$tags = $resp | select tags
$tags.tags
} else {
$tags = $resp | select name
$tags.name
}
Get all tags from Docker Hub: this command uses the command-line JSON processor jq to select the tag names from the JSON returned by the Docker Hub Registry (the quotes are removed with tr). Replace library with the Docker Hub user name, debian with the image name:
curl -s 'https://registry.hub.docker.com/v2/repositories/library/debian/tags/' | jq -r '."results"[]["name"]'
To view all available tags in a browser:
https://registry.hub.docker.com/v1/repositories/<username>/<image_name>/tags
i.e. https://hub.docker.com/r/localstack/localstack/tags
Or, you can get a json response using this endpoint:
https://registry.hub.docker.com/v1/repositories/localstack/localstack/tags
My contribution:
Shell script
As short and simple as possible
Requires curl and jq
Uses Docker v2 REST API
Returns all tags using REST API pagination
Example:
$ docker-tags prantlf/chromedriver-headless
latest
102
93
86
Script contents:
#!/bin/sh
image=$1
if [ "$image" == "" ]; then
echo "Usage:
docker-tags <image>
Example:
docker-tags library/ubuntu"
exit 0
fi
page_size=100
page_index=0
while true; do
page_index=$((page_index+1))
results=`curl -L -s "https://registry.hub.docker.com/v2/repositories/$image/tags?page=$page_index&page_size=$page_size" | jq -r 'select(.results != null) | .results[]["name"]'`
if [ $? != 0 ] || [ "$results" == "" ]; then
break
fi
echo "$results"
done
As of 2023, there are a number of tools to do this
regclient
skopeo
crane
reg - hasn't been updates for years, unfortunately. Doesn't work with quay.io.
docker run --rm ghcr.io/regclient/regctl:v0.4.5 tag ls ghcr.io/regclient/regctl
docker run --rm quay.io/skopeo/stable:v1.9.2 list-tags docker://quay.io/skopeo/stable \
| jq -r '.Tags[]'
docker run --rm gcr.io/go-containerregistry/crane ls gcr.io/go-containerregistry/crane
docker run --rm r.j3ss.co/reg:v0.16.1 tags r.j3ss.co/reg
BTW - there are even more tools. This list looks comprehensive:
iximiuz/awesome-container-tinkering.
curl -u <username>:<password> https://$your_registry/v2/$image_name/tags/list -s -o - | \
tr -d '{' | tr -d '}' | sed -e 's/[][]//g' -e 's/"//g' -e 's/ //g' | \
awk -F: '{print $3}' | sed -e 's/,/\n/g'
You can use it if your env has no 'jq', = )
You can use:
skopeo inspect docker://<REMOTE_REGISTRY> --authfile <PULL_SECRET> | jq .RepoTags
Here is a script that lists all tags either with 2 or 3 digits.
You can get the code directly on github
https://github.com/youssefalaoui/dockerhub-tools/blob/main/dockerhub-list-tags.sh
dockerhub_list_tags()
{
#local LOCAL_IMAGE LOCAL_GET_TWO_DIGITS_VERSIONS
LOCAL_IMAGE=${1:-null}
LOCAL_GET_TWO_DIGITS_VERSIONS=${2:-true}
if [[ $LOCAL_IMAGE == "" || $LOCAL_IMAGE == null ]]
then
printf "Image name is required: %s" ${FUNCNAME[0]};
exit 1;
fi
#[[ $LOCAL_IMAGE == "" || $LOCAL_IMAGE == null ]] && printf "Image name is required: %s" ${FUNCNAME[0]}; exit 1;
echo "Listing tags from docker hub for your image '$LOCAL_IMAGE'"
# Check if 2 digits format is requested, otherwise, show it in normal format
if [[ "$LOCAL_GET_TWO_DIGITS_VERSIONS" == true ]]; then
DOCKERHUB_LIST_TAGS=($(curl -L -s "https://registry.hub.docker.com/v2/repositories/$LOCAL_IMAGE/tags?page_size=1024"|jq '."results"[]["name"]' | sed 's/"//g' | sed 's/\.[^.]*$//'))
else
DOCKERHUB_LIST_TAGS=($(curl -L -s "https://registry.hub.docker.com/v2/repositories/$LOCAL_IMAGE/tags?page_size=1024"|jq '."results"[]["name"]' | sed 's/"//g'))
fi
for TAG in ${DOCKERHUB_LIST_TAGS[#]}
do
echo $TAG
done
}
# Test example
dockerhub_list_tags "library/nginx" false
You can also use this scrap :
# vim /usr/sbin/docker-tags
& Append Following (as it is):
#!/bin/bash
im="$1"
[[ -z "$im" ]] && { echo -e '\e[31m[-]\e[39m Where is the image name ??' ; exit ; }
[[ -z "$(echo "$im"| grep -o '/')" ]] && { link="https://hub.docker.com/r/library/$im/tags/" ; } || { link="https://hub.docker.com/r/$im/tags/" ; }
resp="$(curl -sL "$link")"
err="$(echo "$resp" | grep -o 'Page Not Found')"
if [[ ! -z "$err" ]] ; then
echo -e "\e[31m[-]\e[39m No Image Found with name => [ \e[32m$im\e[39m ]"
exit
else
tags="$(echo "$resp"|sed -e 's|}|\n|g' -e 's|{|\n|g'|grep '"result"'|sed -e 's|,|\n|g'|cut -d '[' -f2|cut -d ']' -f1|sed '/"tags":/d'|sed -e 's|"||g')"
echo -e "\e[32m$tags\e[39m"
fi
Make it Executable :
# chmod 755 /usr/sbin/docker-tags
Then Finally Try By :
$ docker-tags testexampleidontexist
[-] No Image Found with name => [ testexampleidontexist ]
$ docker search ubuntu
$ docker-tags teamrock/ubuntu
latest
[ Hope you are aware of $ & # before running any command ]
If folks want to read tags from the RedHat registry at https://registry.redhat.io/v2 then the steps are:
# example nodejs-12 image
IMAGE_STREAM=nodejs-12
REDHAT_REGISTRY_API="https://registry.redhat.io/v2/rhel8/$IMAGE_STREAM"
# Get an oAuth token based on a service account username and password https://access.redhat.com/articles/3560571
TOKEN=$(curl --silent -u "$REGISTRY_USER":"$REGISTRY_PASSWORD" "https://sso.redhat.com/auth/realms/rhcc/protocol/redhat-docker-v2/auth?service=docker-registry&client_id=curl&scope=repository:rhel:pull" | jq --raw-output '.token')
# Grab the tags
wget -q --header="Accept: application/json" --header="Authorization: Bearer $TOKEN" -O - "$REDHAT_REGISTRY_API/tags/list" | jq -r '."tags"[]'
If you want to compare what you have in your local openshift registry against what is in the upstream registry.redhat.com then here is a complete script.
The Docker Registry API has an endpoint to list all tags.
Looks like Tutum has a similar endpoint, as well as a way to access via tutum-cli.
With the tutum-cli, try the following:
tutum tag list <uuid>
In powershell 5.1, I have a simple list_docker_image_tags.ps1 script like this:
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$image
)
$url = "https://registry.hub.docker.com/v1/repositories/{0}/tags" -f $image
Invoke-WebRequest $url | ConvertFrom-Json | Write-Output
Then I can grep for 4.7 tags like this:
./list_docker_image_tags.ps1 microsoft/dotnet-framework | ?{ $_.name -match "4.7" }
Here's an answer that's applicable for v2 of the registry.
If you have jq and curl installed on your machine:
curl https://registry.hub.docker.com/v2/repositories/$REPOSITORY/tags?page_size=10000 | jq '.results[] | { name: .name, architectures: ([ (.images[] | if .variant? then .os + "/" + .architecture + .variant? else .os + "/" + .architecture end) ] | join(", ")) }'
For instance, running this command for the curlimages/curl repository yields:
{
"name": "latest",
"architectures": "linux/ppc64le, linux/s390x, linux/arm64, linux/386, linux/armv7, linux/amd64"
}
{
"name": "7.78.0",
"architectures": "linux/armv7, linux/arm64, linux/386, linux/s390x, linux/ppc64le, linux/amd64"
}
{
"name": "7.77.0",
"architectures": "linux/ppc64le, linux/arm64, linux/s390x, linux/armv7, linux/386, linux/amd64"
}
{
"name": "7.76.1",
"architectures": "linux/386, linux/arm64, linux/armv7, linux/ppc64le, linux/s390x, linux/amd64"
}
{
"name": "7.76.0",
"architectures": "linux/armv7, linux/386, linux/s390x, linux/amd64, linux/ppc64le, linux/arm64"
}
{
"name": "7.75.0",
"architectures": "linux/armv7, linux/ppc64le, linux/386, linux/amd64, linux/arm64, linux/s390x"
}
{
"name": "7.74.0",
"architectures": "linux/armv7, linux/386, linux/amd64, linux/ppc64le, linux/s390x, linux/arm64"
}
{
"name": "7.73.0",
"architectures": "linux/arm64, linux/armv7, linux/s390x, linux/ppc64le, linux/amd64, linux/386"
}
{
"name": "7.72.0",
"architectures": "linux/s390x, linux/amd64, linux/arm64, linux/386, linux/ppc64le, linux/armv7"
}
{
"name": "7.71.1",
"architectures": "linux/s390x, linux/arm64, linux/ppc64le, linux/amd64, linux/386, linux/armv7"
}
{
"name": "7.71.0",
"architectures": "linux/arm64, linux/ppc64le, linux/386, linux/s390x, linux/amd64, linux/armv7"
}
{
"name": "7.70.0",
"architectures": "linux/386, linux/arm64, linux/s390x, linux/amd64, linux/ppc64le, linux/armv7"
}
{
"name": "7.69.1",
"architectures": "linux/amd64"
}
{
"name": "7.69.0",
"architectures": "linux/amd64"
}
{
"name": "7.68.0",
"architectures": "linux/amd64"
}
{
"name": "7.67.0",
"architectures": "linux/amd64"
}
{
"name": "7.66.0",
"architectures": "linux/amd64"
}
{
"name": "7.65.3",
"architectures": "linux/amd64"
}
Edit:
In answer to the question:
How can I list all tags of a Docker image on a remote Docker registry using the CLI (preferred) or curl?
Preferably without pulling all versions from the remote registry. I just want to list the tags.
To get all the tags for an image you can use "curl" to get the specific image you want and pipe the output into "jq" to extract the information.
curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/python/tags?page_size=1024'|jq '.results[]["name"]'
Output (truncated not the full list):
"3.9-windowsservercore"
"alpine3.14"
"alpine3.13"
"alpine"
"3.9.8-alpine3.14"
"3.9.8-alpine3.13"
"3.9.8-alpine"
Further should you need additional information from the registry you can access additional field information like this.
This command will give you both the tags and the size of the image which might be useful to have too.
curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/python/tags?page_size=1024'|jq '.results[] as $results | ($results["name"] + " - " + ($results["full_size"] | tostring))'
Output (truncated not the full list):
"3.9-windowsservercore - 2241040278"
"alpine3.14 - 17565702"
"alpine3.13 - 17556181"
"alpine - 17565702"
"3.9.8-alpine3.14 -17362557"
"3.9.8-alpine3.13 - 17353629"
"3.9.8-alpine - 17362557"
There is a lot of duplication among the answers given thus far.
Most of them fail to take into account that the GitHub API (at least v2) will never return more than 100 results at a time, even if you ask for more. I noticed this when requesting the tags for php.
The following script works around this.
It only works for public repositories.
#!/bin/sh
# list the tags on Docker Hub for the given image(s)
# thank you, https://stackoverflow.com/questions/28320134/how-can-i-list-all-tags-for-a-docker-image-on-a-remote-registry
TagsFor()
{
curl -L -s 'https://registry.hub.docker.com/v2/repositories/library/'$1'/tags?page='$2'&page_size'=$3
}
for i in "$#"
do
TagsFor "$i" 1 10 |
jq -r .count |
while read nr_of_tags
do
nr_of_pages=`expr $nr_of_tags / 100`
seq 1 $nr_of_pages |
while read p
do
TagsFor "$i" "$p" 100 |
jq -r '.results[] | .name'
done
done
done
I just ran the script; it retrieved 7200 php tags. For all I know, it may be running into yet another API limit, but 7200 >> 100.
I have done this thing when I have to implement a task in which if user somehow type the wrong tag then we have to give the list of all the tag present in the repo(Docker repo) present in the register.
So I have code in batch Script.
<html>
<pre style="background-color:#bcbbbb;">
#echo off
docker login --username=xxxx --password=xxxx
docker pull %1:%2
IF NOT %ERRORLEVEL%==0 (
echo "Specified Version is Not Found "
echo "Available Version for this image is :"
for /f %%i in (' curl -s -H "Content-Type:application/json" -X POST -d "{\"username\":\"user\",\"password\":\"password\"}" https://hub.docker.com/v2/users/login ^|jq -r .token ') do set TOKEN=%%i
curl -sH "Authorization: JWT %TOKEN%" "https://hub.docker.com/v2/repositories/%1/tags/" | jq .results[].name
)
</pre>
</html>
So in this we can give arguments to out batch file like: Dockerfile java version7
Building on #AlexForbes's answer I've improved the api v2 docker-registry-list.py to support:
– slashes in the repository name (eg curlimages/curl) and
– private repos (authentication by username and password)
https://github.com/axil/docker-registry-list
Usage:
./docker-registry-list.py -u dockerid -p password dockerid/myrepo
Output:
{
"name": "dockerid/myrepo",
"tags": [
"1.0"
]
}
Was looking for an sdk in java that I could use to hit the Docker V2 API but couldn't find one. Repo here for anyone that might find it useful: https://github.com/fern-api/docker-registry-api.
Should be possible to generate in other languages too, feel free to open an issue on the repo!