-
Notifications
You must be signed in to change notification settings - Fork 18.7k
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
add support for image inspect with containerd-integration #43818
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
fe465a1
to
7e7249c
Compare
Would it be possible to split the "ctx" changes into a separate commit? |
moved it to #43828 |
cfa4765
to
157e515
Compare
157e515
to
1184eb5
Compare
1184eb5
to
ee27455
Compare
ee27455
to
f4f6760
Compare
805e2c6
to
e35edac
Compare
daemon/containerd/image.go
Outdated
} | ||
|
||
if len(digests) > 1 { | ||
return containerdimages.Image{}, errdefs.NotFound(errors.New("ambiguous reference")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe errdefs.Conflict
would be more suitable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conflict (409
) is mostly intended if there's a conflict with another request (e.g. update a container that is in the process of being deleted); that said; "it's hard", as those status codes weren't really designed with APIs in mind. Also see the discussion on #44685
This page has some flow-charts that have been quite useful; https://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html
Maybe a 422
would make sense, but it's not about the body
(although that may be semantics)
daemon/containerd/image.go
Outdated
@@ -20,6 +20,7 @@ import ( | |||
"github.com/docker/docker/image" | |||
"github.com/docker/docker/layer" | |||
"github.com/docker/go-connections/nat" | |||
"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not comfortable with having our internal types defined by another project; see the discussion on rumpl#121 (comment)
If that type is implementing the image "v1" spec defined in this repository (https://github.com/moby/moby/tree/master/image/spec), and we don't have a type for that in this repository, we should define it here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the commit
daemon/containerd/image.go
Outdated
exposedPorts[nat.Port(k)] = v | ||
} | ||
|
||
img := image.NewImage(image.IDFromDigest(ctrdimg.Target.Digest)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just recalled #44426 - we should update this to
img := image.NewImage(image.IDFromDigest(ctrdimg.Target.Digest)) | |
img := image.NewImage(image.ID(ctrdimg.Target.Digest)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 👍
6228c7a
to
1d1988c
Compare
daemon/containerd/image.go
Outdated
if platform != nil { | ||
cs := i.client.ContentStore() | ||
imgPlatforms, err := containerdimages.Platforms(ctx, cs, img.Target) | ||
if err != nil { | ||
return img.Target, err | ||
} | ||
|
||
comparer := platforms.Only(*platform) | ||
for _, p := range imgPlatforms { | ||
if comparer.Match(p) { | ||
return img.Target, nil | ||
} | ||
} | ||
return img.Target, errdefs.NotFound(errors.Errorf("%s: platform %s not supported by image", refOrID, platforms.Format(*platform))) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be extracted from resolveDescriptor
to GetImage
. Accepting platform
as an argument to this function gives an impression that the returned descriptor will be platform specific and it doesn't.
The platform is relevant only in the GetImage
context, which uses it to pick the correct image config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I moved the code
daemon/containerd/image.go
Outdated
|
||
cs := i.client.ContentStore() | ||
|
||
platform := platforms.Default() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, this won't work, if we have image for the non-default platform only (like if we only do docker pull --platform linux/arm64 alpine
on non-arm64 host).
Is this expected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense that when no --platform
flag is given then we consider this as the user asking for the current platform
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That bugs me - if the user doesn't set the --platform
then we don't know what he's asking for, consider this:
$ docker pull --platform linux/arm64 alpine
$ docker inspect alpine
alpine: platform linux/amd64 not supported by image
seems a bit harsh, especially for doing an inspect
which should allow me to get information about an image. The user might not remember which platform the image was pulled for and currently there's no way for him to find out that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should we show in this case then?
$ docker pull --platform linux/arm64 alpine
$ docker pull --platform linux/s390x alpine
$ docker inspect alpine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "old" behavior would be to pick the first platform that's found (but of course that would always be the only platform). Ideally we would show all platforms for the image, but that brings us to the discussion in #44582. If we must show a single architecture, but multiple architectures are present, it could follow the same method of selecting as a docker pull
would do (basically, use a platform-matcher?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider the API currently shows whatever image is currently there regardless of platform.
We could error out with like ambiguous image reference: multiple platforms are available, you must specify a platform: available platforms <platform1>,<platform2>
. It would be nice, though, if the API's json error could list those platforms so clients can parse it nicely (without having to parse the error string) or pick the first one... I'm inclined to error in case of ambiguity here, though.
Alternatively... we could update the API to return a list of objects
The docker CLI at least already outputs a json array.
There wouldn't be much too change to support the updated API.
... or change it to return the image index (with the appropriate media type on the response headers).
This does mean larger changes would be needed on the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the last point... we could gate this by accept header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talking with @thaJeztah and we decided to go with a AllPlatformsWithPreference that returns the preferred platform first and then the others in order that they are defined by containerd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^^ That approach is the "first step" for this PR, to keep the behavior (mostly) consistent with what we have pre-containers, and to get us going, but we should indeed continue the discussion on UX (which could be return multiple platforms if there's multiple variations present)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely, the discussion is only getting started. Way back when we talked about snapshotters we decided that the way to go was to make everything as close as possible to the existing and after that we can shape the things in different ways
daemon/containerd/image.go
Outdated
|
||
platform := platforms.Default() | ||
if desc.Platform != nil { | ||
platform = platforms.OnlyStrict(*desc.Platform) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use OnlyStrict
here, but Only
when doing the previous check which will make some cases pass the check but fail on getting the config. Maybe we could get rid of the previous platform check completely, and rely on containerdimages.Config
returning an error when we don't have that platform present?
Outside of the discussion around multiple platforms being available, the rest of the code LGTM. |
40f184f
to
82430d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
type ErrImageDoesNotExist struct { | ||
ref reference.Reference | ||
Ref reference.Reference | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a follow-up; we need to check if we really need this error-type, as it already implements errdefs.NotFound
, perhaps we don't need it (with the possible exception of the "special" No such ...
prefix, which may be needed for older CLIs).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this one might not be needed, the only difference is that this error type formats the message with "No such image: %s", ref
whereas the errdefs.NotFound
doesn't have that extra data
This is a squashed version of various PRs (or related code-changes) to implement image inspect with the containerd-integration; - add support for image inspect - introduce GetImageOpts to manage image inspect data in backend - GetImage to return image tags with details - list images matching digest to discover all tags - Add ExposedPorts and Volumes to the image returned - Refactor resolving/getting images - Return the image ID on inspect - consider digest and ignore tag when both are set - docker run --platform Signed-off-by: Djordje Lukic <djordje.lukic@docker.com> Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com> Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still LGTM
Let me bring this one in 👍 |
} | ||
|
||
func (c allPlatformsWithPreferenceMatcher) Less(p1, p2 ocispec.Platform) bool { | ||
return c.preferred.Less(p1, p2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is to live in a pkg
package, we should make sure it's robust for any preferred
matcher, including ones whose Less
implementation may not necessarily sort platforms which Match
less than platforms it would not.
return c.preferred.Less(p1, p2) | |
m1, m2 := c.preferred.Match(p1), c.preferred.Match(p2) | |
if m1 && m2 { | |
return c.preferred.Less(p1, p2) | |
} | |
return m1 // Not totally-ordered |
Upstreaming:
These patches were selected by looking at the history for https://github.com/rumpl/moby/commits/dd-4.15.0/daemon/containerd/image.go, and only the relevant parts for this feature were included.
Quite a few of those are touching-up previous commits, so we should consider squashing (some of) them, but keeping them separate for now to somewhat help review.
Also included rumpl#122
This is a squashed version of various PRs (or related code-changes)
to implement image inspect with the containerd-integration;
- A picture of a cute animal (not mandatory but encouraged)