summaryrefslogtreecommitdiffstats
path: root/classes
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-01-14 04:46:12 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-01-21 18:00:26 -0500
commit2b1fa9e5a62f27186823539e748cc48718cd79e9 (patch)
tree61a1a5067dc5028c52fdf01cc8b4bd86c37befde /classes
parent08ffbeef62a426193528c539bcb02fa4b8b1c191 (diff)
downloadmeta-virtualization-2b1fa9e5a62f27186823539e748cc48718cd79e9.tar.gz
container-bundle: add CONTAINER_BUNDLE_DEPLOY for base layer use
Add CONTAINER_BUNDLE_DEPLOY variable to enable dual-use of container-bundle: 1. Target packages (existing): Creates installable packages for target container storage (Docker/Podman) 2. Base layer source (new): When CONTAINER_BUNDLE_DEPLOY = "1", also deploys the fetched OCI image to DEPLOY_DIR_IMAGE for use as a base layer via OCI_BASE_IMAGE This enables fetching external images (docker.io, quay.io) and using them as base layers for Yocto-built container images. Example usage: # recipes-containers/oci-base-images/alpine-oci-base_3.19.bb inherit container-bundle CONTAINER_BUNDLES = "docker.io/library/alpine:3.19" CONTAINER_DIGESTS[docker.io_library_alpine_3.19] = "sha256:..." CONTAINER_BUNDLE_DEPLOY = "1" # Then in your app container recipe: OCI_BASE_IMAGE = "alpine-oci-base" IMAGE_INSTALL = "myapp" Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'classes')
-rw-r--r--classes/container-bundle.bbclass65
1 files changed, 65 insertions, 0 deletions
diff --git a/classes/container-bundle.bbclass b/classes/container-bundle.bbclass
index 27aa81ea..3d3f3a16 100644
--- a/classes/container-bundle.bbclass
+++ b/classes/container-bundle.bbclass
@@ -160,6 +160,9 @@ CONTAINER_BUNDLE_RUNTIME ?= "${@get_bundle_runtime(d)}"
160# Inherit shared functions for multiconfig/machine/arch mapping 160# Inherit shared functions for multiconfig/machine/arch mapping
161inherit container-common 161inherit container-common
162 162
163# Inherit deploy for optional OCI base layer deployment (see CONTAINER_BUNDLE_DEPLOY)
164inherit deploy
165
163# Dependencies on native tools 166# Dependencies on native tools
164# vcontainer-native provides vrunner.sh 167# vcontainer-native provides vrunner.sh
165# Blobs come from multiconfig builds (vdkr-initramfs-create, vpdmn-initramfs-create) 168# Blobs come from multiconfig builds (vdkr-initramfs-create, vpdmn-initramfs-create)
@@ -409,3 +412,65 @@ FILES:${PN} = "${datadir}/container-bundles"
409# from container image recipes. Circular deps only occur if bundle packages are 412# from container image recipes. Circular deps only occur if bundle packages are
410# globally added to all images (including container images themselves). 413# globally added to all images (including container images themselves).
411do_compile[mcdepends] = "mc::${VRUNTIME_MULTICONFIG}:vdkr-initramfs-create:do_deploy mc::${VRUNTIME_MULTICONFIG}:vpdmn-initramfs-create:do_deploy" 414do_compile[mcdepends] = "mc::${VRUNTIME_MULTICONFIG}:vdkr-initramfs-create:do_deploy mc::${VRUNTIME_MULTICONFIG}:vpdmn-initramfs-create:do_deploy"
415
416# ===========================================================================
417# Optional Deploy for OCI Base Layer Usage
418# ===========================================================================
419#
420# When CONTAINER_BUNDLE_DEPLOY = "1", this class also deploys fetched remote
421# containers to DEPLOY_DIR_IMAGE for use as base layers with OCI_BASE_IMAGE.
422#
423# This enables dual-use recipes that both:
424# 1. Create installable packages for target container storage
425# 2. Provide OCI base layers for building layered containers
426#
427# Example:
428# # alpine-oci-base.bb
429# inherit container-bundle
430# CONTAINER_BUNDLES = "docker.io/library/alpine:3.19"
431# CONTAINER_DIGESTS[docker.io_library_alpine_3.19] = "sha256:..."
432# CONTAINER_BUNDLE_DEPLOY = "1"
433#
434# # Then in another recipe:
435# OCI_BASE_IMAGE = "alpine-oci-base"
436#
437CONTAINER_BUNDLE_DEPLOY ?= ""
438
439python () {
440 if d.getVar('CONTAINER_BUNDLE_DEPLOY') == "1":
441 # Inherit deploy class dynamically
442 bb.build.addtask('do_deploy', 'do_build', 'do_compile', d)
443}
444
445do_deploy() {
446 if [ "${CONTAINER_BUNDLE_DEPLOY}" != "1" ]; then
447 bbnote "CONTAINER_BUNDLE_DEPLOY not set, skipping deploy"
448 return 0
449 fi
450
451 # Deploy fetched OCI directories to DEPLOY_DIR_IMAGE for use as base layers
452 # Format: ${PN}-latest-oci/ (matches what image-oci.bbclass expects)
453
454 if [ ! -d "${WORKDIR}/fetched" ]; then
455 bbwarn "No fetched containers to deploy"
456 return 0
457 fi
458
459 # Find the first (primary) fetched OCI directory
460 oci_dir=$(ls -d ${WORKDIR}/fetched/*/ 2>/dev/null | head -1)
461 if [ -z "$oci_dir" ] || [ ! -f "$oci_dir/index.json" ]; then
462 bbfatal "No valid OCI directory found in ${WORKDIR}/fetched/"
463 fi
464
465 bbnote "Deploying OCI base layer: $oci_dir -> ${DEPLOYDIR}/${PN}-latest-oci"
466
467 install -d ${DEPLOYDIR}
468 cp -rL "$oci_dir" ${DEPLOYDIR}/${PN}-${PV}-oci
469
470 # Create symlinks for OCI_BASE_IMAGE lookup
471 ln -sfn ${PN}-${PV}-oci ${DEPLOYDIR}/${PN}-latest-oci
472}
473do_deploy[dirs] = "${DEPLOYDIR}"
474
475# Only add sstate for deploy when enabled
476SSTATE_SKIP_CREATION:task-deploy = "${@'' if d.getVar('CONTAINER_BUNDLE_DEPLOY') == '1' else '1'}"