-
Notifications
You must be signed in to change notification settings - Fork 2k
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 OCI support to manifest subcommand #3990
Conversation
Signed-off-by: Justin Chadwell <me@jedevc.com>
This behavior should not break any more use cases than before. Previously, if the mismatch occured, we would actually push a manifest that we then never referred to in the manifest list! If this was done in a new repository, the command would fail with an obscure error from the registry - the content wouldn't exist with the descriptor we expect it to. Signed-off-by: Justin Chadwell <me@jedevc.com>
This prevents us needing to attempt to reconstruct the exact indentation registry side, which is not canonical - so may differ. Signed-off-by: Justin Chadwell <me@jedevc.com>
I've started working on manifest merging: it's a bit trickier, we need some more logic in the store, but it works 🎉 I won't put it into this PR, since it's some more substantial changes, but here's the initial sketch: jedevc/cli@manifest-oci...jedevc:cli:manifest-merging. |
@@ -14,6 +14,7 @@ | |||
"variant": "v7" | |||
} | |||
}, | |||
"Raw": "ewogICAic2NoZW1hVmVyc2lvbiI6IDIsCiAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5kaXN0cmlidXRpb24ubWFuaWZlc3QudjIranNvbiIsCiAgICJjb25maWciOiB7CiAgICAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5jb250YWluZXIuaW1hZ2UudjEranNvbiIsCiAgICAgICJzaXplIjogMTUyMCwKICAgICAgImRpZ2VzdCI6ICJzaGEyNTY6NzMyOGY2ZjhiNDE4OTA1OTc1NzVjYmFhZGM4ODRlNzM4NmFlMGFjYzUzYjc0NzQwMWViY2U1Y2YwZDYyNDU2MCIKICAgfSwKICAgImxheWVycyI6IFsKICAgICAgewogICAgICAgICAibWVkaWFUeXBlIjogImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLAogICAgICAgICAic2l6ZSI6IDE5OTA0MDIsCiAgICAgICAgICJkaWdlc3QiOiAic2hhMjU2Ojg4Mjg2ZjQxNTMwZTkzZGZmZDRiOTY0ZTFkYjIyY2U0OTM5ZmZmYTRhNGM2NjVkYWI4NTkxZmJhYjAzZDQ5MjYiCiAgICAgIH0KICAgXQp9", |
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.
Silly question; would JSON-in-JSON (raw data, but as string) work? I realise this data is not primarily intended for users to read, but having something to hold-onto when looking at it could still be useful (instead of having to decode)
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, so we still have the content from the registry in the file as a sub-object, since deprecating that would probably be way more work 😢
As long as we have that, and Raw
just duplicates that content full with indentation, I'm happy to have it be unreadable base64 😄 Especially as the content fed to the hashing algorithm isn't a string, it's a bytes array, keeping in as close format to the original is easier IMO.
No super strong preferences here, though I admit I'm not a fan of JSON-in-JSON 👀
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 some discussion happening on base64 vs JSON-in-JSON 😅
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.
After @neersighted describing a preference for base64 here, I'm convinced -- the data is still available, and the Go struct should mostly match anyways for users. Additionally, jq
has a base64 decoder built-in, so it's still very very accessible (~ jq '.Raw | @base64d | fromjson'
).
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.
base64 is great 👍
|
||
// SchemaV2Manifest is used for inspection | ||
// TODO: Deprecate this and store manifest blobs |
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.
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, I actually prefer the base64 encoding as the it makes it more obvious this is an opaque blob.
dt, err = json.MarshalIndent(imageManifest.OCIManifest, "", " ") | ||
if err != nil { | ||
return mountRequest{}, err | ||
} |
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.
It just occurred to me; as this is "net new"; should we error in this case (no raw data present) instead of re-constructing the manifest data?
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 I prefer the symmetry with the manifest v2 -- or at the very least, if we reconstruct for one and not the other, we should make it more obvious why that happens in the code.
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.
Agreed, I think the symmetry makes sense.
I'm curious though - here I've used 2-spaces as "the default". In hindsight, 3 spaces might make more sense? BuildKit did used to produce 3-space OCI images, so maybe it makes more sense to use the same 3 spaces as for schema2?
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 curious though - here I've used 2-spaces as "the default". In hindsight, 3 spaces might make more sense? BuildKit did used to produce 3-space OCI images, so maybe it makes more sense to use the same 3 spaces as for schema2?
I guess there's no "good" answer for that one. Quick thoughts;
- In practice, we should never® hit this branch; existing
~/.docker/manifests/..
JSON files would not have OCI manifests, and new files will have theRaw
field propagated - If we want to keep symmetry; we could also consider going the reverse path; for existing files that have the "struct", but don't have the
Raw
field propagated;- add the
Raw
data (based on the struct), using the "old" formatting (3 spaces) - or (worst case); try 3 spaces, and if that doesn't match the digest, try 2 spaces, and otherwise bail out?
- deprecate this code-path (only use
.Raw
)
- add the
I guess it's fine to leave those for a follow-up.
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, let's bring this one in
Is the change supported in RHEL8? |
@TalWeisler it's part of the docker cli v23.0.0 and up, so if you have that package installed, then it should be supported. We don't provide packages for RHEL (other than for s390x architectures), but you should be able to install the CentOS 8 packages (see https://docs.docker.com/engine/install/centos/) |
Thanks @thaJeztah.
|
@TalWeisler ah, thanks for that; that looks like a possible bug. What registry are you testing this against? Is that Docker Hub, or another registry? I can see two (potential) issues here;
|
@thaJeztah Headers:
|
|
I did a quick check to see what headers it passes; here's a quick "registry" to debug the requests; package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.Method, r.URL, r.Header)
w.Write([]byte("{}"))
})
_ = http.ListenAndServe(":5001", nil)
} Now running docker manifest inspect --insecure localhost:5001/foo/bar I get these logs:
So (besides the
So, I think that looks good.
Yes, that looks odd. I did a quick search, and found a reference to that (invalid) mediatype in 3 locations; 2 in github.com/anchore/harbor-scanner-adapter; https://github.com/anchore/harbor-scanner-adapter/blob/aafc46f138503405e4419afe758d3b6173a5624e/pkg/adapter/adapter.go#L10 DockerImageMimeType = "application/vnd.oci.image.manifest.v2+json" 1 in some comment describing that Buildah must produce that mediatype for Docker # Container format for podman. Required to build containers with "ManifestType": "application/vnd.oci.image.manifest.v2+json",
export BUILDAH_FORMAT=docker
I did find code in the CNCF distribution repository about that error, but don't see it handling wrong media types. I do think it's odd to return a 404 (and not a 415), but that may have been for backward compatibility. It's worth looking though if that's defined somewhere in the spec. |
@thaJeztah Thank you! |
Fixes moby/moby#43126.
- What I did
Introduced support for OCI images to the
docker manifest
command.- How I did it
https://github.com/distribution/distribution/ already support oci schemas, so all we need to do is connect into it. A few minor changes to the on-disk storage format are also required to correct whitespace issues 😢
This is incredibly not beautiful set of patches, but given docker manifest doesn't see active development, I'm not sure it's worth refactoring too much of the structure of the code.
Ideally, as a follow-up I'd like to add support to merge manifest lists together - this is proving a little tricky though.
- How to verify it
Use
docker manifest
with an OCI image!- Description for the changelog
Add support for OCI images to docker manifest
- A picture of a cute animal (not mandatory but encouraged)
cc @thaJeztah @crazy-max