buildah
buildah copied to clipboard
support for oras-like sugar
As far as I can tell, generally the core skopeo copy workflow is functional when using OCI artifacts. However, operating on artifacts is clunky; the most ergonomic way is to fetch into an oci directory and then parse the content (and if you just wanted the data, delete the temporary oci dir). For uploads it requires e.g. creating content in a local oci directory e.g. and then pushing to a registry.
The ORAS project has much nicer higher level sugar; especially things like oras push:
oras push --artifact-type application/vnd.me.config localhost:5000/hello:v1 hi.txt
is quite nice.
WDYT about adding some commands like this to skopeo?
Just came out of a call with @baude working in this area. In general, I think it would be great to provide means to create OCI artifacts more easily.
I am under the impression that you're looking more into creating artifacts (since copying them is already supported by Skopeo). In that case, I think that Buildah is probably a better home for that functionality. Or even extending umoci?
@nalind is also looking into SBOMs and artifacts at the moment AFAIR.
In that case, I think that Buildah is probably a better home for that functionality. Or even extending umoci?
Not opposed to buildah for this functionality; feels like it can go either way? In theory skopeo is more about inspection/copying, but OTOH this desired functionality is very close to "copying" too. There's no "containerization" involved here (namespaces, cgroups, overlayfs, etc etc.), it's just wrapping files in JSON.
Restating the above, one dividing line here is that IMO at a technical level this does not involve containers/storage and eventually I think it could make sense to drop the vendored copy of containers/storage out of skopeo and have it defer to the installed buildah/podman binary for that.
As far as umoci, today it's not shipped in RHEL and I'd definitely like something that is for this.
For me, the primary boundary is: Skopeo should not be in the business of editing blob contents. That’s clearly what Buildah is, for container layers. Secondarily, I’d be wary of any kind of concept of “staging/WIP” and edit commands, even with whole blobs; that suggests that some kind of artifact-type-specific tool would be a better fit, possibly calling c/image to do the registry operations.
In that sense, a “push an artifact with these raw blobs” (creating just a manifest) is close but probably on the “reasonable to include” side. (It’s not that easy as the example shows… At least every blob needs a MIME type specified.)
Apart from skopeo sync, Skopeo is a very simple/dumb wrapper around c/image, with little UI design and quite little required maintenance. And, past experience is skopeo sync is, sadly, not getting the attention it probably deserves. There’s the chicken-and-egg problem of a very small project with little attention required vs. a very small project with little spare capacity available. Solvable, of course, but needs to be considered as something to solve if the feature set were to grow significantly, beyond that one example (which would be an one-off thing, and certainly manageable).
Now, Buildah is designed around c/storage and storing data in layers there; storing other arbitrary large blobs in c/storage is possible but I’m not sure it’s wanted; there’s not that much obvious benefit and the locking required by c/storage might mean that dealing with large artifacts could slow down otherwise unrelated pulls/pushes/container starts in the same store. So I can vaguely imagine that Buildah, as it exists right now, might not actually be the best answer either, and maybe Skopeo could be the place.
eventually I think it could make sense to drop the vendored copy of containers/storage out of skopeo
c/storage in Skopeo is one of those things that is useless and inconvenient 99% of the time (notably its dependencies are one of the stronger reasons we can’t provide a single static Skopeo binary that runs on all distributions, something a class of users wants) — and then very useful in rare support cases.
My wish is that every single caller of alltransports.ParseImageName accepts the same transports with the same syntax, with docker:// and dir: and …. and, yes, containers-storage:. (In many cases, the right call is not to call alltransports.ParseImageName in the first place!). In that sense, it Would Look Bad™️ if Skopeo, the poster child of c/image, did not do that. Now, of course, that “wish” is an architecture astronaut thing with not that much relevance to end users.
In that sense, a “push an artifact with these raw blobs” (creating just a manifest) is close but probably on the “reasonable to include” side. (It’s not that easy as the example shows… At least every blob needs a MIME type specified.)
Right, that was my sense too.
Syntax
I guess regardless of whether it goes in skopeo or buildah (mostly) - any opinions on syntax?
I think my bikeshed here would be:
Pushing
skopeo ociartifact push (--export-manifest manifest.json) [IMAGE] [FILENAME]:[MIMETYPE]...
e.g.:
skopeo ociartifact push quay.io/example/configmap:latest foo.json:application/vnd.containers.configmap+json bar.json:application/vnd.containers.configmap+json
and
skopeo ociartifact push quay.io/example/diskimage:latest fedora-coreos.qcow2:application/vnd.coreos.disk+qcow2
Unlike oras we make the mime type required, because skopeo already has commands for pushing OCI images.
Pulling
skopeo copy quay.io/example/configmap:latest oci:myartifact
No new command! This already exists and works.
skopeo ociartifact extract quay.io/example/configmap:latest foo.json
This will write the contents of foo.json to stdout. Handy for streaming to other tools, etc.
skopeo ociartifact extract --single quay.io/example/configmap:latest
Assuming that there is only one referenced blob, extract it to stdout.
Both of these commands would take --export-manifest to also save the manifest (e.g. one may want version metadata e.g.)
Now, Buildah is designed around c/storage and storing data in layers there; storing other arbitrary large blobs in c/storage is possible but I’m not sure it’s wanted;
It's definitely unwanted; use cases here include e.g. storing .qcow2 images directly as an artifact in a registry, and we want to go directly from .qcow-in-filesystem to registry, not indirect through c/storage. That said, just because something is in buildah doesn't mean that it has to indirect through c/storage of course.
I guess regardless of whether it goes in skopeo or buildah (mostly) - any opinions on syntax?
- Separate CLI arguments for MIME type and file paths, please. We already painted ourselves into that corner with
oci-archive:path:tag making it impossible topodman load archive-path:with-colon.tar. - I think the destination should be a transport
:name, not registry-specific. (I don’t quite feel strongly enough to call it a blocker, but it’s close.) - The OCI image format actually strongly differentiates between config (almost, but not quite, mandatory) and layers. It would probably be convenient to make “the first” argument the config, and the rest layers, I just want to be an intentional decision.
Maybe something like
skopeo oci-artifact push docker://quay.io/… {-c|--config-mime-type}application/foo.metadata foo.json{-m|--mime-type}application/foo.data blob1.bin[{-m|--mime-type} application/foo.extra] blob2.bin
with -m mandatory before the first blob but optional for the following ones (continuing to use the previous value)?
- The
extractpart might not be necessary (inspect --config --raw), or alternatively needs some more mechanisms for dealing with config vs. one of the potentially many layers. - Unsure: I’m not sure that
--export-manifestis necessary as such; what is the consumer going to do with the raw bytes?skopeo copyhas--digestfile, is that roughly the idea?
Also Cc: @flouthoc @nalind — I’m not sure whether these or similar, conversations, have been happening elsewhere as well.
We already painted ourselves into that corner with oci-archive:path:tag making it impossible to podman load archive-path:with-colon.tar.
Yeah, true. Agree it's unclean. Has it been a problem in practice though?
Maybe something like
My main concern with this is that usually arguments aren't positionally sensitive, it should be equivalent to specify them as FLAGS ARGS where FLAGS are things that start with - and ARGS don't (except for a flag that binds to an argument of course).
Dunno. Probably not a big deal.
Hmm, I think a , can't appear in a media type (since it's in tspecials here right?), so another alternative is to reverse things and do skopeo oci-artifact push [IMAGE] [MEDIATYPE],[FILE]
skopeo oci-artifact push quay.io/example/diskimage:latest application/vnd.coreos.disk+qcow2,fedora-coreos.qcow2
hmm, in the general case we may want support for accepting separate local filenames and remote org.opencontainers.image.title names...messy. I don't think oras supports this.
I'm OK with having separate arguments; visually noisier but in the end I expect most usage of this is from scripts or at worst humans copy/pasting instructions.
(Also the use cases I primarily care about have exactly one layer, in which case the argument ordering doesn't matter)
Unsure: I’m not sure that --export-manifest is necessary as such; what is the consumer going to do with the raw bytes? skopeo copy has --digestfile, is that roughly the idea?
Key metadata in the manifest: version aka org.opencontainers.image.version, timestamp aka org.opencontainers.image.created - plus digest of the whole manifest.
We already painted ourselves into that corner with oci-archive:path:tag making it impossible to podman load archive-path:with-colon.tar.
Yeah, true. Agree it's unclean. Has it been a problem in practice though?
https://github.com/containers/podman/issues/489 (internal) https://github.com/containers/podman/issues/18673 (external reporter), at least.
My main concern with this is that usually arguments aren't positionally sensitive, it should be equivalent to specify them as
FLAGS ARGS
Yes. I don’t know that there is another trivial ergonomic solution… eventually we might end up accepting a JSON input, which clearly works but also takes a lot of pleasure out of using the tool. …
Hmm, I think a
,can't appear in a media type (since it's intspecialshere right?), so another alternative is to reverse things and doskopeo oci-artifact push [IMAGE] [MEDIATYPE],[FILE]
… oh, look a non-trivial solution :) That looks promising. The trivial version would require specifying the MIME type on every argument, but special-casing ,file or something like that would work, even if inelegantly.
hmm, in the general case we may want support for accepting separate local filenames and remote
org.opencontainers.image.titlenames...messy. I don't thinkorassupports this.
I’m not sure what you mean. Should this create a side image using the OCI referrers mechanism? (That, to me feels like a separate subcommand, and anyway c/image can’t currently do that.) Or is it just an annotation string?
Unsure: I’m not sure that --export-manifest is necessary as such; what is the consumer going to do with the raw bytes? skopeo copy has --digestfile, is that roughly the idea?
Key metadata in the manifest: version aka
org.opencontainers.image.version, timestamp akaorg.opencontainers.image.created- plus digest of the whole manifest.
At least for …image.version, that seems backwards to me: When creating the artifact, Skopeo itself has no idea what the value should be, it would have to come from the caller as an option.
I feel very weakly about .created — it could, plausibly, be automatically set, but for symmetry that might be an incoming option as well. Or just let the caller set arbitrary annotations [… on which of the many fields? All of them?] and be done with it.
Buildah has already a hidden set of commands (see buildah source) to create a "source image" OCI artifact. I don't think we'll need that anymore but there is a precedent in Buildah that shows how artifacts can be build. It doesn't use c/storage at all for that but operates exclusively with the docker: and oci: transport. I am sure we can generalize that code fairly easily into a generic artifact building tool. I am sure @baude and @rhatdan will be supportive of such efforts - the timing seems right.
But I'd prefer to move the details of the design into a separate design doc/proposal/pr. May that be an .md or a Google Doc or something else - but something that allows for an easy iterative review.
That makes sense to me, I don't see us having to lock everything into containers/storage for buildah. Creating and assembling manifests and pushing them to a container/registry seems like a legitimate use case.
That makes sense to me,
That = carrying this in buildah or carrying it in skopeo?
When creating the artifact, Skopeo itself has no idea what the value should be, it would have to come from the caller as an option. ... . Or just let the caller set arbitrary annotations
Yes, oras has -a, --annotation stringArray, so a full invocation might look like e.g.:
skopeo oci-artifact push -a 'org.opencontainers.image.version=38.20231011.7' quay.io/example/diskimage:latest application/vnd.coreos.disk+qcow2,fedora-coreos.qcow2
I feel very weakly about .created — it could, plausibly, be automatically set,
oras does this by default; I think it makes sense, but clearly needs to be overridable too.
buildah support.
I think skopeo might changing what the tool does.
(transferred this issue to buildah)
FWIW ( not directly related ) better support to push OCI artifacts is also needed so its easier to ship WASM modules ( for which podman is currently using scratch based OCI images ) if it becomes easier to work with artifacts, I think podman should switch to artifacts to ship wasm modules as well like other tools in the ecosystem.
A friendly reminder that this issue had no activity for 30 days.
xref https://github.com/CentOS/centos-bootc-layered/pull/21#issuecomment-1865199943
One thing that got slightly lost here is that even if we choose buildah to build, we still probably want skopeo and podman to support fetching.
Not sure podman has any better support for fetching the buildah pull, but definitely better for running containers.
I ran across buildah source recently but functionality isn't there for me to be able to depend on it for my use cases (i.e. https://github.com/containers/buildah/issues/5399). I wanted to change from our current default of oras, but regctl also looked like it had a nice interface.
I ran across
buildah sourcerecently but functionality isn't there for me to be able to depend on it for my use cases (i.e. #5399). I wanted to change from our current default of oras, but regctl also looked like it had a nice interface.
@arewm Created a PR for this: https://github.com/containers/buildah/pull/5454