All of lore.kernel.org
 help / color / mirror / Atom feed
* [meta-virtualization][PATCH 1/2] image-oci: add OCI runtime bundle output
@ 2026-09-30 14:47 Tanguy Raufflet
  2026-09-30 14:47 ` [meta-virtualization][PATCH 2/2] app-container-oci-bundle.bb: add a new demo recipe using an OCI bundle Tanguy Raufflet
  2026-09-30 15:56 ` [meta-virtualization][PATCH 1/2] image-oci: add OCI runtime bundle output Bruce Ashfield
  0 siblings, 2 replies; 4+ messages in thread
From: Tanguy Raufflet @ 2026-09-30 14:47 UTC (permalink / raw)
  To: meta-virtualization; +Cc: enguerrand.de-ribaucourt, Tanguy Raufflet

umoci currently uses an OCI runtime bundle as a temporary artifact
because umoci needs this intermediate representation to construct an OCI
image with the rootfs populated. After this step, the bundle is not used
anymore since umoci does not provide a mechanism to directly configure
the runtime bundle directly.

Because some utilities expect an OCI runtime bundle as input (e.g.,
crun, runc), it is useful to optionally retain the bundle after
constructing the OCI image. The comment [1] in the code was already
suggesting that retaining the OCI runtime bundle could be beneficial.

    "We could make this optional, since the bundle is directly runnable
    via runc"

This commit adds OCI_IMAGE_BUNDLE_OUTPUT to optionally deploy the
runtime bundle as a tar archive into IMGDEPLOYDIR. This bundle contains
the fully populated OCI runtime bundle, including the rootfs and the
config.json file reflecting the final OCI image configuration.

Also, a postprocess command can be specified to either modify the
runtime bundle's configuration or replace it entirely before it is
archived.

Note that image_bundle_name is not generated to the IMGDEPLOYDIR anymore
to avoid issues when BitBake processes and caches files under
IMGDEPLOYDIR.

Signed-off-by: Tanguy Raufflet <tanguy.raufflet@savoirfairelinux.com>
---
 classes/image-oci-umoci.inc | 41 ++++++++++++++++++++++--
 classes/image-oci.bbclass   | 13 ++++++++
 docs/container-bundling.md  | 64 +++++++++++++++++++++++++++++++++++++
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/classes/image-oci-umoci.inc b/classes/image-oci-umoci.inc
index 67f6c6e5..ad103f16 100644
--- a/classes/image-oci-umoci.inc
+++ b/classes/image-oci-umoci.inc
@@ -421,6 +421,34 @@ PYEOF
     bbnote "OCI fix: Layer whiteout fix complete"
 }
 
+oci_archive_bundle() {
+    image_tag="${@d.getVar("OCI_IMAGE_TAG").replace(":", "_")}"
+
+    ${IMAGE_CMD_TAR} --sort=name --format=posix --pax-option=delete=atime,delete=ctime --numeric-owner \
+        -cf "${IMGDEPLOYDIR}/${IMAGE_NAME}.oci-bundle.tar" \
+        -C "${OCI_BUNDLE_DIR}" \
+        .
+
+    ln -sfn "${IMAGE_NAME}.oci-bundle.tar" \
+        "${IMGDEPLOYDIR}/${IMAGE_BASENAME}-$image_tag-oci-bundle.tar"
+
+    rm -rf "${OCI_BUNDLE_DIR}"
+}
+
+python oci_bundle_postprocess() {
+    from oe.utils import execute_pre_post_process
+
+    execute_pre_post_process(
+        d, d.getVar('OCI_BUNDLE_POSTPROCESS_COMMAND')
+    )
+    bb.build.exec_func('oci_archive_bundle', d)
+}
+
+oci_bundle_postprocess[dirs] = "${OCI_BUNDLE_DIR}"
+
+do_image_oci[postfuncs] += "${@'oci_bundle_postprocess' if bb.utils.to_boolean(d.getVar('OCI_IMAGE_BUNDLE_OUTPUT')) else ''}"
+do_image_oci[subimages] += "${@'oci-bundle.tar' if bb.utils.to_boolean(d.getVar('OCI_IMAGE_BUNDLE_OUTPUT')) else ''}"
+
 IMAGE_CMD:oci() {
     umoci_options=""
 
@@ -477,7 +505,7 @@ IMAGE_CMD:oci() {
 
     new_image=t
     image_name="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci"
-    image_bundle_name="${IMAGE_NAME}${IMAGE_NAME_SUFFIX}-oci-bundle"
+    image_bundle_name="${OCI_BUNDLE_DIR}"
     if [ -n "$OCI_REUSE_IMAGE" ]; then
 	if [ -d $image_name ]; then
 	    bbdebug 1 "OCI: reusing image directory"
@@ -816,8 +844,15 @@ IMAGE_CMD:oci() {
 	ln -sfn "$image_name-dir.tar" "${IMAGE_BASENAME}-$image_tag-oci-dir.tar"
     fi
 
-    # We could make this optional, since the bundle is directly runnable via runc
-    rm -rf $image_bundle_name
+    if [ "${OCI_IMAGE_BUNDLE_OUTPUT}" = "1" ]; then
+        # Refresh config.json from the finalized image before post-processing.
+        umoci raw runtime-config --rootless \
+            --image "$image_name:${OCI_IMAGE_TAG}" \
+            --rootfs "$image_bundle_name/rootfs" \
+            "$image_bundle_name/config.json"
+    else
+        rm -rf "$image_bundle_name"
+    fi
 
     # This is the OCI image directory, which is technically the "image" as specified
     # Use -n to avoid creating link inside existing symlink target directory
diff --git a/classes/image-oci.bbclass b/classes/image-oci.bbclass
index 141cd2a8..cbbaa388 100644
--- a/classes/image-oci.bbclass
+++ b/classes/image-oci.bbclass
@@ -280,6 +280,19 @@ OCI_LAYER_CACHE_DIR ?= "${TOPDIR}/oci-layer-cache/${MACHINE}"
 # bundled into a tarball.
 OCI_IMAGE_TAR_OUTPUT ?= "true"
 
+# Create a tar archive containing an OCI runtime bundle suitable for OCI runtimes such as crun.
+OCI_IMAGE_BUNDLE_OUTPUT ?= "0"
+
+# Functions appended here run after the final runtime configuration is generated
+# and before the bundle is archived. The bundle directory is available as
+# OCI_BUNDLE_DIR.
+OCI_BUNDLE_DIR = "${WORKDIR}/${IMAGE_BASENAME}-oci-bundle"
+OCI_BUNDLE_POSTPROCESS_COMMAND ?= ""
+
+python () {
+    d.setVarFlag('OCI_BUNDLE_POSTPROCESS_COMMAND', 'vardeps', d.getVar('OCI_BUNDLE_POSTPROCESS_COMMAND'))
+}
+
 # Generate a subarch that is appropriate to OCI image
 # types. This is typically only ARM architectures at the
 # moment.
diff --git a/docs/container-bundling.md b/docs/container-bundling.md
index 77aa09b0..bedd541e 100644
--- a/docs/container-bundling.md
+++ b/docs/container-bundling.md
@@ -288,6 +288,70 @@ Disable caching with `OCI_LAYER_CACHE = "0"` if you:
 - Need fully reproducible builds with no local state
 - Are debugging package installation issues
 
+### OCI Runtime Bundles
+
+The umoci backend can emit an OCI runtime bundle suitable for runtimes such
+as crun and runc:
+
+    OCI_IMAGE_BUNDLE_OUTPUT = "1"
+
+The `app-container-oci-bundle` demo image enables this output and can be
+built with `bitbake app-container-oci-bundle`.
+
+The runtime configuration is generated from the finalized OCI image, so its
+`config.json` includes settings applied through `OCI_IMAGE_ENV_VARS`,
+`OCI_IMAGE_CMD`, `OCI_IMAGE_ENTRYPOINT`, `OCI_IMAGE_RUNTIME_UID`, and
+`OCI_IMAGE_WORKINGDIR`. It is deployed as:
+
+    ${IMAGE_BASENAME}-${OCI_IMAGE_TAG}-oci-bundle.tar
+
+with the convenience symlink:
+
+    ${IMAGE_BASENAME}-oci-bundle.tar
+
+`OCI_IMAGE_BUNDLE_OUTPUT` is independent of `OCI_IMAGE_TAR_OUTPUT`. The
+latter controls tar output for the OCI image layout (`index.json` and
+`blobs/`), while the runtime bundle contains `config.json` and `rootfs/`.
+
+Extract and run the bundle with crun:
+
+    mkdir my-container-bundle
+    tar -xf my-container-oci-bundle.tar -C my-container-bundle
+    crun run --bundle my-container-bundle my-container
+
+#### Bundle Post-processing
+
+Functions listed in `OCI_BUNDLE_POSTPROCESS_COMMAND` run after the finalized
+image is unpacked and before the bundle is archived. They run with
+`OCI_BUNDLE_DIR` as their current working directory:
+
+```bitbake
+OCI_BUNDLE_POSTPROCESS_COMMAND += "configure_runtime_bundle;"
+
+configure_runtime_bundle() {
+    config="config.json"
+    jq '.process.terminal = false' "$config" > "$config.tmp"
+    mv "$config.tmp" "$config"
+}
+```
+
+Post-processing changes only the emitted runtime bundle. It does not modify
+the OCI image configuration or its filesystem layers.
+
+To replace `config.json` completely, add the replacement to `SRC_URI` and
+install it from a post-processing function:
+
+```bitbake
+SRC_URI += "file://config.json"
+
+OCI_BUNDLE_POSTPROCESS_COMMAND += "install_runtime_config;"
+
+install_runtime_config() {
+    install -m 0644 "${WORKDIR}/config.json" \
+    "config.json"
+}
+```
+
 ### OCI_IMAGE_CMD vs OCI_IMAGE_ENTRYPOINT
 
     # CMD (default) - replaced when user passes arguments
-- 
2.55.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-12 12:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-30 14:47 [meta-virtualization][PATCH 1/2] image-oci: add OCI runtime bundle output Tanguy Raufflet
2026-09-30 14:47 ` [meta-virtualization][PATCH 2/2] app-container-oci-bundle.bb: add a new demo recipe using an OCI bundle Tanguy Raufflet
2026-09-30 15:56 ` [meta-virtualization][PATCH 1/2] image-oci: add OCI runtime bundle output Bruce Ashfield
2026-10-12 12:24   ` Tanguy Raufflet

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.