Adding Docker API endpoint to inspect image manifest#32061
Adding Docker API endpoint to inspect image manifest#32061thaJeztah merged 4 commits intomoby:masterfrom
Conversation
There was a problem hiding this comment.
Not sure how to retrieve platform information from a schema2.DeserializedManifest. Working on figuring this out.
d7084ee to
3525180
Compare
There was a problem hiding this comment.
This part is a little unclear based on the backed.GetRepository function as it is right now. Maybe it should be possible for it to just take a reference.Named object instead of reference.NamedTagged, since it doesn't seem to depend on having the latter.
3525180 to
2c159d5
Compare
|
Bumping up this PR. It works in the current form, and the goal is for the client to be able to use this endpoint to get manifest information to construct an appropriate spec. |
2c159d5 to
22ae2ba
Compare
api/server/router/image/image.go
Outdated
There was a problem hiding this comment.
I made it POST because we needed to send registry auth token for private repos. But since we send it in the header instead of the payload, is GET fine?
2bb96d1 to
6d04d48
Compare
|
Architecture information is updated for all types of manifests now. |
6d04d48 to
2ce8435
Compare
api/types/registry/registry.go
Outdated
There was a problem hiding this comment.
What about returning the top-level manifest itself instead of (or in addition to) the digest? I could imagine this being useful for some things.
We could also return an optional config blob if one is referenced by the top-level manifest.
Then the platform determination could be done on the client side, making this /manifest more generic.
It's still not really ideal, because the daemon is deciding what items to fetch from the registry and return to the client. I kind of like the idea of proxying the registry API through the daemon, but that's a pretty big project and probably way out of scope for what we're trying to do here.
That said, I don't feel strongly about any of this, and I could be okay with just returning specific fields such as Platforms in the API response if that's what people prefer.
There was a problem hiding this comment.
@aaronlehmann I'm inclined towards making it as general as possible. So returning the top-level manifest (and config blob) sounds like a better idea, especially because then the client can deal with it as it likes.
Also, then any format updates have to be dealt with by the client only.
There was a problem hiding this comment.
@aaronlehmann as an example, what do you think about
{
Digest digest.Digest,
Manifest distribution.Manifest,
ConfigJSON []bytes,
}
I still think we'd have to separate cases (fat, v2, v1 manifests) to get the right config blob, but then the client could Unmarshal it as desired.
There was a problem hiding this comment.
Yeah, that's basically what I had in mind. Although maybe Manifest should be []byte so that we aren't introducing distribution types into the API, and also so that the digest can be verified. It's ugly to put JSON inside JSON though.
There was a problem hiding this comment.
Do you mean marshaling the manifest into []byte before sending? I have a couple of questions
- Why does the digest need to be verified at the client?
- Why does sending
[]byteshelp with it?
It's ugly to put JSON inside JSON though
This applies to ConfigJSON as well, right?
There was a problem hiding this comment.
The manifest is a JSON document. DeserializedManifest is just a convenience for working with it in Go code. If you marshal it to JSON, you'll get the same set of bytes back, so the hash won't change (DeserializedManifest implements a MarshalJSON method that ensures this).
However, I've thought about it some more, and I don't think using []byte is worth the ugliness. Let's do this instead:
{
Digest digest.Digest
Manifest *json.RawMessage
ConfigJSON *json.RawMessage
}Manifest would contain the original manifest JSON returned by (*DeserializedManifest).MarshalJSON. This is similar to using []byte, but it causes the JSON to be inserted directly instead of as a string. We lose the ability to verify the digest (because of possible whitespace added around the value during the marshalling process), but we avoid the ugliness off putting JSON inside a string inside JSON.
Why does the digest need to be verified at the client?
I don't think there's an immediate reason to verify the digest at the client, but I was thinking that if we're going to send the manifest to the client, we might as well send the exact manifest.
Why does sending []bytes help with it?
Because the hash is computed over these bytes.
It's ugly to put JSON inside JSON though
This applies to ConfigJSON as well, right?
Yes.
There was a problem hiding this comment.
@aaronlehmann PTAL, does this look reasonable?
73bc289 to
c7c2b74
Compare
There was a problem hiding this comment.
Presumably this should return an error
There was a problem hiding this comment.
non-blocking: it might be slightly more readable to use a type switch here. It's purely a cosmetic suggestion, though.
api/types/registry/registry.go
Outdated
There was a problem hiding this comment.
I guess since we're potentially returning different kinds of manifests in this field (schema1, schema2, manifest list...), we should have another field containing the media type. Depending which kind of manifest is being returned, this field would either be set to schema1.MediaTypeSignedManifest, schema2.MediaTypeManifest, or manifestlist.MediaTypeManifestList.
There was a problem hiding this comment.
Ah, I intended to add this but missed it. Doing it now.
69e56a7 to
8181648
Compare
|
@aaronlehmann addressed all comments. |
8181648 to
a23ae7b
Compare
api/types/registry/registry.go
Outdated
api/types/registry/registry.go
Outdated
There was a problem hiding this comment.
I suggest adding the omitempty flag, as this field won't always be present.
There was a problem hiding this comment.
Let's move the lines related to ConfigJSON into the *schema2.DeserializedManifest case so that manifestInspect.ConfigJSON remains nil when other types of manifests are returned.
There was a problem hiding this comment.
@aaronlehmann I wasn't sure if there was a ConfigJSON we could return for FAT manifests, so I put it here. It doesn't seem to be the case, so I'll move this.
a9262a9 to
4d336db
Compare
|
@aaronlehmann PTAL. |
|
Just one comment... it may be a good idea to override the descriptor's media type always, not just in the |
|
@aaronlehmann sure, updating the PR. If we're going to call |
4d336db to
409fc20
Compare
aaronlehmann
left a comment
There was a problem hiding this comment.
Possible cleanup: dscrptr is no longer necessary because distributionInspect.Descriptor can be set directly. Not important though.
LGTM
Signed-off-by: Nishant Totla <[email protected]>
409fc20 to
12e232e
Compare
|
@aaronlehmann thanks, I cleaned that up. |
| Features: | ||
| type: "array" | ||
| items: | ||
| type: "string" |
There was a problem hiding this comment.
Looks like empty array definitions are still causing an error, I'm fixing those.
There was a problem hiding this comment.
Can we come up with some sample URL's and/or fill the OSVersion / Variants? Or do you think it's ok to keep them empty?
There was a problem hiding this comment.
@thaJeztah In the examples I saw, these weren't filled, so I think it's okay. I can try to search for better examples later.
| type: "string" | ||
| Size: | ||
| type: "integer" | ||
| format: "int64" |
There was a problem hiding this comment.
Wondered if this should be an uint64, but I see it's coming from an existing type
8babced to
2878fda
Compare
Signed-off-by: Nishant Totla <[email protected]>
2878fda to
4a81204
Compare
|
@thaJeztah PTAL. |
|
I think We're almost there; left one comment on the example, also (sorry, forgot to mention); this needs an entry in the API history; https://github.com/moby/moby/blob/master/docs/api/version-history.md#v130-api-changes |
|
@thaJeztah updated API history here: #33147 |


The goal of this PR is to make it possible for the client to figure out the image manifest, which will allow the client to construct the spec with the full digest (instead of doing it in the daemon like #28173) and platform information (#31348).
The client can make a call to the Engine to retrieve the manifest.
Here are more details about the change:
- What I did
Added
/distribution/{name:*}/jsonendpoint in the API, that accesses the registry and pulls the manifest. This is required to pull digest and platform information.- How I did it
I added a new
distributionRouter, and a function calledgetDistributionInfoindistribution_routes.gothat accesses the registry to get the digest, and pulls the image manifest to get more information. ADistributionInspectstruct is returned.- How to verify it
Send a
curlrequest to the engine, athttp:/distribution/alpine:latest/json- Description for the changelog
Adding Docker API endpoint to inspect image manifest
- A picture of a cute animal (not mandatory but encouraged)
(\__/)
(='.'=)
(")_(")
I'm on a weak wifi, so here's a text bunny.
What I will do after this PR: