2.7 KiB
2.7 KiB
Container Registry Tag Queries
This reference details how to discover available image tags across common container registries without requiring external tooling.
1. Docker Hub (hub.docker.com)
Docker Hub provides an unauthenticated v2 API for public repositories.
Official Images (Library)
For top-level images like postgres, redis, traefik, mariadb:
IMAGE="postgres"
curl -s "https://registry.hub.docker.com/v2/repositories/library/${IMAGE}/tags?page_size=100" \
| python3 -c '
import sys, json
data = json.load(sys.stdin)
tags = [t["name"] for t in data.get("results", [])]
print("\n".join(tags[:30]))
'
Community / User Images
For namespace images like adguard/adguardhome, prom/prometheus, grafana/alloy:
ORG="adguard"
IMAGE="adguardhome"
curl -s "https://registry.hub.docker.com/v2/repositories/${ORG}/${IMAGE}/tags?page_size=100" \
| python3 -c '
import sys, json
data = json.load(sys.stdin)
tags = [t["name"] for t in data.get("results", [])]
print("\n".join(tags[:30]))
'
2. GitHub Container Registry (ghcr.io)
GHCR implements OCI distribution spec. Public image tags can be queried with an anonymous bearer token.
IMAGE="xtls/xray-core"
TOKEN=$(curl -s "https://ghcr.io/token?scope=repository:${IMAGE}:pull" | python3 -c 'import sys, json; print(json.load(sys.stdin)["token"])')
curl -s -H "Authorization: Bearer ${TOKEN}" "https://ghcr.io/v2/${IMAGE}/tags/list" \
| python3 -c '
import sys, json
data = json.load(sys.stdin)
tags = data.get("tags", [])
print("\n".join(sorted(tags, reverse=True)[:30]))
'
3. Quay.io (quay.io)
Quay provides a REST API:
REPO="repository_name"
curl -s "https://quay.io/api/v1/repository/${REPO}/tag/?limit=50&onlyActiveTags=true" \
| python3 -c '
import sys, json
data = json.load(sys.stdin)
tags = [t["name"] for t in data.get("tags", [])]
print("\n".join(tags[:30]))
'
4. SemVer Matching & Sorting
When filtering tags to find the latest stable version matching the current container's flavor:
import re
def parse_semver(tag: str):
# Match patterns like v1.2.3, 1.2.3-alpine, 16.4
m = re.match(r"^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-(.+))?$", tag)
if not m:
return None
major = int(m.group(1))
minor = int(m.group(2) or 0)
patch = int(m.group(3) or 0)
flavor = m.group(4) or ""
return (major, minor, patch, flavor)
Rules for candidate selection:
- Preserve flavor: If currently running
16-alpine, match only tags with suffix-alpine. - Ignore pre-releases: Filter out tags containing
alpha,beta,rc,dev,test, or git SHAs. - Classify:
- Same
major, higherminororpatch-> Minor / Patch. - Higher
major-> Major (requires Step 5 approval).
- Same