-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved visibility / discovery of images and artifacts #476
Comments
If helpful, here is a reference with related JSON content that would produce the results like shown on GHCR or for ReproductionFROM alpine
RUN echo 'hello' > /tmp/hello.txt # Docker Engine 28.0.1, buildx v0.21.1, BuildKit 0.20.0
# Run zot
docker run --rm -d --name zot -p 127.0.0.1:5000:5000 ghcr.io/project-zot/zot:v2.1.2
# Build image and push to zot
# Differs from defaults with:
# - x86_64 + aarch64 multi-arch image
# - Full provenance (instead of minimal, forces using an index even if only a single platform)
# - OCI media types for manifest/index and artifacts (instead of Docker equivalent types)
docker buildx build --builder custom-builder \
--output 'type=image,push=true,oci-mediatypes=true,oci-artifact=true' \
--platform 'linux/amd64,linux/arm64' \
--provenance true \
--tag localhost:5000/hello/world:example \
. Image indexHere is the main image index content (with the misleading # Digest:
$ docker buildx imagetools inspect --raw localhost:5000/hello/world:example | sha256sum
bb2d3b5ffb87b7bc0f5f7bf08c31e0d32c950c1238e67f868eb5fbc2313ce291 -
# JSON output:
docker buildx imagetools inspect --raw localhost:5000/hello/world:example {
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda",
"size": 668,
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:8c57cad131a6458bc17679475de6d9dd2fd5da21e4ee88a1e52774722b210652",
"size": 668,
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:4e7545e0a6306b658f3896724ec8d9b5d0b6b055394bb7a2d40816676d6ac0f9",
"size": 914,
"annotations": {
"vnd.docker.reference.digest": "sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda",
"vnd.docker.reference.type": "attestation-manifest"
},
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:b71d18d0f25ba530053c3551fe65105974da76fee2949adc3539e60be8a67ead",
"size": 914,
"annotations": {
"vnd.docker.reference.digest": "sha256:8c57cad131a6458bc17679475de6d9dd2fd5da21e4ee88a1e52774722b210652",
"vnd.docker.reference.type": "attestation-manifest"
},
"platform": {
"architecture": "unknown",
"os": "unknown"
}
}
]
} While these attestation entries probably shouldn't exist in the image index above AFAIK, it is what Docker will do by default when publishing an image to a registry (unless choosing to opt-out of attestations via Discovery
# Install oras:
$ curl -fsSL https://github.com/oras-project/oras/releases/download/v1.2.2/oras_1.2.2_linux_amd64.tar.gz \
| tar -xz --directory /usr/local/bin/ oras
# NOTE: zot supports the Referrers API, other registries like ghcr.io presently only support Referrers Tag schema
# Platform must be provided, otherwise response is to the image index for the tag (as shown above)
$ oras discover localhost:5000/hello/world:example
localhost:5000/hello/world@sha256:bb2d3b5ffb87b7bc0f5f7bf08c31e0d32c950c1238e67f868eb5fbc2313ce291
# Only supports querying one platform at a time:
$ oras discover --platform linux/amd64 localhost:5000/hello/world:example
localhost:5000/hello/world@sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda
└── application/vnd.docker.attestation.manifest.v1+json
└── sha256:4e7545e0a6306b658f3896724ec8d9b5d0b6b055394bb7a2d40816676d6ac0f9
# Alternatively query the image manifest for a specific platform directly (same output as above):
$ oras discover localhost:5000/hello/world@sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda
localhost:5000/hello/world@sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda
└── application/vnd.docker.attestation.manifest.v1+json
└── sha256:4e7545e0a6306b658f3896724ec8d9b5d0b6b055394bb7a2d40816676d6ac0f9 Querying the artifact: docker buildx imagetools inspect --raw \
localhost:5000/hello/world@sha256:4e7545e0a6306b658f3896724ec8d9b5d0b6b055394bb7a2d40816676d6ac0f9 {
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"artifactType": "application/vnd.docker.attestation.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.empty.v1+json",
"digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
"size": 2,
"data": "e30="
},
"layers": [
{
"mediaType": "application/vnd.in-toto+json",
"digest": "sha256:f7dcb411e73877667c88cb7a33170a2702a5c229ebd164ebafe73d78c3230be7",
"size": 3253,
"annotations": {
"in-toto.io/predicate-type": "https://slsa.dev/provenance/v0.2"
}
}
],
"subject": {
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"digest": "sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda",
"size": 668,
"platform": {
"architecture": "amd64",
"os": "linux"
}
}
} NOTE: The
Extra content
# NOTE: `docker buildx imagetools inspect` doesn't support inspecting this content:
oras blob fetch --output - \
localhost:5000/hello/world@sha256:f7dcb411e73877667c88cb7a33170a2702a5c229ebd164ebafe73d78c3230be7 \
jq . SLSA provenance attestation - Collapsed for brevity{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "pkg:docker/localhost%3A5000/hello/world@example?platform=linux%2Famd64",
"digest": {
"sha256": "a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda"
}
}
],
"predicate": {
"builder": {
"id": ""
},
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
"digest": {
"sha256": "a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "Dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"locals": [
{
"name": "context"
},
{
"name": "dockerfile"
}
]
},
"environment": {
"platform": "linux/amd64"
}
},
"buildConfig": {
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"source": {
"identifier": "docker-image://docker.io/library/alpine:latest@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c"
}
},
"platform": {
"Architecture": "amd64",
"OS": "linux"
},
"constraints": {}
}
},
{
"id": "step1",
"op": {
"Op": {
"exec": {
"meta": {
"args": [
"/bin/sh",
"-c",
"echo 'hello' > /tmp/hello.txt"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"cwd": "/",
"removeMountStubsRecursive": true
},
"mounts": [
{
"dest": "/"
}
]
}
},
"platform": {
"Architecture": "amd64",
"OS": "linux"
},
"constraints": {}
},
"inputs": [
"step0:0"
]
},
{
"id": "step2",
"op": {
"Op": {}
},
"inputs": [
"step1:0"
]
}
],
"digestMapping": {
"sha256:70726ed3fd80dc09e300177733bc0725a3b2b791bd320619b0413aacad7fe174": "step0",
"sha256:7a55f424c6be9b60b97d32b6976811eb01d1be9388fc4d224ae29bc83d7dfa37": "step2",
"sha256:a2db6c754eb861c73eae55ff6f737068ab7d4889174a6958ac21c0fd0567e47d": "step1"
}
},
"metadata": {
"buildInvocationID": "3hqi1x2c5r1o4miy0lmnbk34t",
"buildStartedOn": "2025-03-10T22:56:53.713090832Z",
"buildFinishedOn": "2025-03-10T22:56:55.495878007Z",
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"reproducible": false,
"https://mobyproject.org/buildkit@v1#metadata": {
"source": {
"locations": {
"step0": {
"locations": [
{
"ranges": [
{
"start": {
"line": 1
},
"end": {
"line": 1
}
}
]
}
]
},
"step1": {
"locations": [
{
"ranges": [
{
"start": {
"line": 2
},
"end": {
"line": 2
}
}
]
}
]
}
},
"infos": [
{
"filename": "Dockerfile",
"language": "Dockerfile",
"data": "RlJPTSBhbHBpbmUKUlVOIGVjaG8gJ2hlbGxvJyA+IC90bXAvaGVsbG8udHh0Cg==",
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"source": {
"identifier": "local://dockerfile",
"attrs": {
"local.differ": "none",
"local.followpaths": "[\"Dockerfile\",\"Dockerfile.dockerignore\",\"dockerfile\"]",
"local.sharedkeyhint": "dockerfile"
}
}
},
"constraints": {}
}
},
{
"id": "step1",
"op": {
"Op": {}
},
"inputs": [
"step0:0"
]
}
],
"digestMapping": {
"sha256:8d375c186bde98710c4818219c484181623bead4bfa6ac2feb767b268dbae9cd": "step0",
"sha256:d540ce15ecc33b3e803176988e69e6023188f128deb38b5966a6e91c5cc4e125": "step1"
}
}
]
},
"layers": {
"step0:0": [
[
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:f18232174bc91741fdf3da96d85011092101a032a93a388b79e99e69c2d5c870",
"size": 3642247
}
]
],
"step1:0": [
[
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:f18232174bc91741fdf3da96d85011092101a032a93a388b79e99e69c2d5c870",
"size": 3642247
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:935e4938154b3cc8b5d6c92b652110cca3295483871f9b08f4f01ae8960989b6",
"size": 139
}
]
]
}
}
}
}
} Similar JSON queries for the `linux/amd64` imageImage Manifest: docker buildx imagetools inspect --raw \
localhost:5000/hello/world@sha256:a42bc525fcf382ea7160b037fe72444dc5a415bf8c874e9432814d22ddb61dda {
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"digest": "sha256:22a3cd305250e171afdb759a5494bd2cb30412583217904d33126de010411075",
"size": 821
},
"layers": [
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:f18232174bc91741fdf3da96d85011092101a032a93a388b79e99e69c2d5c870",
"size": 3642247
},
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:935e4938154b3cc8b5d6c92b652110cca3295483871f9b08f4f01ae8960989b6",
"size": 139
}
]
} Image Config: docker buildx imagetools inspect --raw \
localhost:5000/hello/world@sha256:22a3cd305250e171afdb759a5494bd2cb30412583217904d33126de010411075 {
"architecture": "amd64",
"config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh"
],
"WorkingDir": "/"
},
"created": "2025-03-10T01:45:15.070252511Z",
"history": [
{
"created": "2025-02-14T03:28:36Z",
"created_by": "ADD alpine-minirootfs-3.21.3-x86_64.tar.gz / # buildkit",
"comment": "buildkit.dockerfile.v0"
},
{
"created": "2025-02-14T03:28:36Z",
"created_by": "CMD [\"/bin/sh\"]",
"comment": "buildkit.dockerfile.v0",
"empty_layer": true
},
{
"created": "2025-03-10T01:45:15.070252511Z",
"created_by": "RUN /bin/sh -c echo 'hello' > /tmp/hello.txt # buildkit",
"comment": "buildkit.dockerfile.v0"
}
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:08000c18d16dadf9553d747a58cf44023423a9ab010aab96cf263d2216b8b350",
"sha256:1e1493ca99379ba0abd61fb839843dce247adff565669964824ba6432020fc15"
]
}
} |
For a bit more coverage, this comment covers the Referrers Tag behaviour to compliment the prior comment info. This comment is probably not that useful to These digest tags are not visible / discoverable in GHCR -
|
This looks more like a bug, Will need to check why
does not show in the |
See project-zot#476 In previous implementations the referrers tab only showed the referrers returned at image level, ingnoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. Signed-off-by: Andrei Aaron <[email protected]>
See project-zot#476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. Signed-off-by: Andrei Aaron <[email protected]>
See project-zot#476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. Signed-off-by: Andrei Aaron <[email protected]>
See project-zot#476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. ci: improve e2e job reporting Signed-off-by: Andrei Aaron <[email protected]>
See project-zot#476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. ci: improve e2e job reporting Signed-off-by: Andrei Aaron <[email protected]>
* fix: show referrers pointing to image manifests See #476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. ci: improve e2e job reporting Signed-off-by: Andrei Aaron <[email protected]> * fix: the Uses, Used By, Vulnerabilities, Referred By tabs were not refreshed on changing manifest value Signed-off-by: Andrei Aaron <[email protected]> --------- Signed-off-by: Andrei Aaron <[email protected]>
See project-zot/zui#476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. Also fix refreshing the data shown in the tag details tabs on changing the selected manifest Signed-off-by: Andrei Aaron <[email protected]>
See project-zot/zui#476 In previous implementations the referrers tab only showed the referrers returned at image level, ignoring the referrers returned at manifest level. This is fine for singlearch images, since they are the same. For images containing multiple manifests only index referrers were shown. The current implementation would show both the referrers to the index and the current manifest. Also fix refreshing the data shown in the tag details tabs on changing the selected manifest Signed-off-by: Andrei Aaron <[email protected]>
@polarathene I fixed the referrers tab not getting populated for oci artifacts: #478. WRT
Your assumption about the field created in the config is correct. Also if the created field is missing, we pick the timestamp of the last history entry in the config. I think we can track this as an enhancement.
Besides the ZUI issue, current sync/mirroring logic converts docker mediatypes to oci mediatypes, so the references may be broken due to changing digests. We have a PR in progress which should make this configurable. |
Is your feature request related to a problem?
I'd like to have better visibility of what
zot
is storing.That includes images that have been published previously and become untagged, or when OCI artifacts have been published.
Describe the solution you'd like
Versions Overview - Tagged / Untagged
Something like GHCR "Versions" view would be useful:
It provides an overview of all images associated to an image/repo (not quite familiar with the correct jargon here), allowing you to additionally filter the view by tagged or untagged and interact with the items.
However, I'm not really a fan of the UX inconsistency in presentation there when the digest has an associated tag(s).
delete
button is missing on that one. Deletion UX in general is poor at GHCR beyond basics....
is a button that toggles the visibility of the digest (and it's copy button that non-tagged digests lack).OCI Artifacts - Referral API
GHCR presently lacks support for Referrers API, so when querying via
oras discover
it will fallback to Referrers tag scheme there. GHCR UI presently lacks the ability to distinguish OCI artifacts.In the screenshot above the digests listed were all related to the same multi-arch image (
linux/amd64
+linux/arm64
), while two of those digests are provenance attestation artifacts for their respective platform (which Docker includes these attestations as entries in the image index as theunknown/unknown
platform besides the proper amd64/arm64 platform images):zui
appears to have a view to use the Referrers API to show OCI artifacts belonging to a platform image, but it fails to show anything (perhaps it's just mocked out?):I know this functionality works with
zot
asoras discover
is capable of discovering the related OCI artifacts via the Referrers API.Describe alternatives you've considered
Use an alternative container registry? I've been using
ghcr.io
and DockerHub, but recently triedzot
withzui
.Additional context
Also note that the publish timestamp is when the digest was published / updated at the registry, not necessarily when it was built? (which seems to be what ZUI presents? I think it's using the timestamp from an image manifest configs
created
timestamp)Both are useful but when I interact with an container registry I consider the timestamp to represent activity with the registry, whereas the image itself may annotate a timestamp related to it's build for inspection via a different view.
The text was updated successfully, but these errors were encountered: