diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-01-14 04:47:15 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-02-09 03:32:52 +0000 |
| commit | 4ddc9e489307a31b25600b9073edb09110740fb8 (patch) | |
| tree | 528a535e8c3afd0784bdae385e3ff7f52ad15b20 | |
| parent | fb238ac545516cacd05b085335f249a806261644 (diff) | |
| download | meta-virtualization-4ddc9e489307a31b25600b9073edb09110740fb8.tar.gz | |
recipes: add multi-layer OCI example recipes
Add example recipes demonstrating multi-layer OCI image building:
alpine-oci-base_3.19.bb:
- Fetches Alpine 3.19 from Docker Hub using container-bundle
- Uses CONTAINER_BUNDLE_DEPLOY for use as OCI_BASE_IMAGE source
- Pinned digest for reproducible builds
app-container-alpine.bb:
- Demonstrates external base image usage
- Layers Yocto packages (busybox) on top of Alpine
- Uses OCI_IMAGE_CMD for Docker-like behavior
app-container-layered.bb:
- Demonstrates local base image usage
- Layers Yocto packages on top of container-base
- Uses OCI_IMAGE_CMD for Docker-like behavior
Both app containers produce 2-layer OCI images where the base layer
is shared, reducing storage and transfer costs.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
| -rw-r--r-- | recipes-containers/oci-base-images/alpine-oci-base_3.19.bb | 31 | ||||
| -rw-r--r-- | recipes-demo/images/app-container-alpine.bb | 35 | ||||
| -rw-r--r-- | recipes-demo/images/app-container-layered.bb | 36 |
3 files changed, 102 insertions, 0 deletions
diff --git a/recipes-containers/oci-base-images/alpine-oci-base_3.19.bb b/recipes-containers/oci-base-images/alpine-oci-base_3.19.bb new file mode 100644 index 00000000..706ffb2a --- /dev/null +++ b/recipes-containers/oci-base-images/alpine-oci-base_3.19.bb | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | # SPDX-License-Identifier: MIT | ||
| 2 | # | ||
| 3 | # Alpine OCI base image for use with OCI_BASE_IMAGE | ||
| 4 | # | ||
| 5 | # This recipe fetches Alpine Linux from Docker Hub and deploys it to | ||
| 6 | # DEPLOY_DIR_IMAGE for use as a base layer in multi-layer OCI builds. | ||
| 7 | # | ||
| 8 | # Usage in your container recipe: | ||
| 9 | # OCI_BASE_IMAGE = "alpine-oci-base" | ||
| 10 | # IMAGE_INSTALL = "base-files busybox myapp" | ||
| 11 | # | ||
| 12 | # The Alpine layers will be preserved, and your IMAGE_INSTALL packages | ||
| 13 | # are added as an additional layer on top. | ||
| 14 | |||
| 15 | SUMMARY = "Alpine Linux OCI base image" | ||
| 16 | DESCRIPTION = "Fetches Alpine Linux from Docker Hub for use as an OCI base layer" | ||
| 17 | HOMEPAGE = "https://alpinelinux.org/" | ||
| 18 | LICENSE = "MIT" | ||
| 19 | LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" | ||
| 20 | |||
| 21 | inherit container-bundle | ||
| 22 | |||
| 23 | # Remote container from Docker Hub | ||
| 24 | CONTAINER_BUNDLES = "docker.io/library/alpine:3.19" | ||
| 25 | |||
| 26 | # REQUIRED: Pinned digest for reproducible builds | ||
| 27 | # Get with: skopeo inspect docker://docker.io/library/alpine:3.19 | jq -r '.Digest' | ||
| 28 | CONTAINER_DIGESTS[docker.io_library_alpine_3.19] = "sha256:6baf43584bcb78f2e5847d1de515f23499913ac9f12bdf834811a3145eb11ca1" | ||
| 29 | |||
| 30 | # Enable deployment to DEPLOY_DIR_IMAGE for use as OCI base layer | ||
| 31 | CONTAINER_BUNDLE_DEPLOY = "1" | ||
diff --git a/recipes-demo/images/app-container-alpine.bb b/recipes-demo/images/app-container-alpine.bb new file mode 100644 index 00000000..a685f011 --- /dev/null +++ b/recipes-demo/images/app-container-alpine.bb | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | SUMMARY = "Container image based on Alpine OCI base" | ||
| 2 | LICENSE = "MIT" | ||
| 3 | LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" | ||
| 4 | |||
| 5 | # Use fetched Alpine as base layer | ||
| 6 | OCI_BASE_IMAGE = "alpine-oci-base" | ||
| 7 | |||
| 8 | # Use CMD (not ENTRYPOINT) so `docker run image /bin/sh` works as expected | ||
| 9 | OCI_IMAGE_CMD = "/bin/sh -c 'echo Hello from Alpine-based Yocto container'" | ||
| 10 | |||
| 11 | IMAGE_FSTYPES = "container oci" | ||
| 12 | inherit image | ||
| 13 | inherit image-oci | ||
| 14 | |||
| 15 | IMAGE_FEATURES = "" | ||
| 16 | IMAGE_LINGUAS = "" | ||
| 17 | NO_RECOMMENDATIONS = "1" | ||
| 18 | |||
| 19 | # Add Yocto-built packages on top of Alpine | ||
| 20 | IMAGE_INSTALL = " \ | ||
| 21 | base-files \ | ||
| 22 | base-passwd \ | ||
| 23 | netbase \ | ||
| 24 | busybox \ | ||
| 25 | " | ||
| 26 | |||
| 27 | # Allow build with or without a specific kernel | ||
| 28 | IMAGE_CONTAINER_NO_DUMMY = "1" | ||
| 29 | |||
| 30 | # Workaround /var/volatile for now | ||
| 31 | ROOTFS_POSTPROCESS_COMMAND += "rootfs_fixup_var_volatile ; " | ||
| 32 | rootfs_fixup_var_volatile () { | ||
| 33 | install -m 1777 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/tmp | ||
| 34 | install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/log | ||
| 35 | } | ||
diff --git a/recipes-demo/images/app-container-layered.bb b/recipes-demo/images/app-container-layered.bb new file mode 100644 index 00000000..2762aae1 --- /dev/null +++ b/recipes-demo/images/app-container-layered.bb | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | SUMMARY = "Layered Application container - test OCI_BASE_IMAGE" | ||
| 2 | LICENSE = "MIT" | ||
| 3 | LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" | ||
| 4 | |||
| 5 | # Use container-base as the base layer | ||
| 6 | OCI_BASE_IMAGE = "container-base" | ||
| 7 | |||
| 8 | # Use CMD so `docker run image /bin/sh` works as expected | ||
| 9 | OCI_IMAGE_CMD = "/bin/sh -c 'echo Hello from layered container'" | ||
| 10 | |||
| 11 | IMAGE_FSTYPES = "container oci" | ||
| 12 | inherit image | ||
| 13 | inherit image-oci | ||
| 14 | |||
| 15 | IMAGE_FEATURES = "" | ||
| 16 | IMAGE_LINGUAS = "" | ||
| 17 | NO_RECOMMENDATIONS = "1" | ||
| 18 | |||
| 19 | # Only add packages not in base - this is the "app layer" | ||
| 20 | IMAGE_INSTALL = " \ | ||
| 21 | base-files \ | ||
| 22 | base-passwd \ | ||
| 23 | netbase \ | ||
| 24 | busybox \ | ||
| 25 | curl \ | ||
| 26 | " | ||
| 27 | |||
| 28 | # Allow build with or without a specific kernel | ||
| 29 | IMAGE_CONTAINER_NO_DUMMY = "1" | ||
| 30 | |||
| 31 | # Workaround /var/volatile for now | ||
| 32 | ROOTFS_POSTPROCESS_COMMAND += "rootfs_fixup_var_volatile ; " | ||
| 33 | rootfs_fixup_var_volatile () { | ||
| 34 | install -m 1777 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/tmp | ||
| 35 | install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/log | ||
| 36 | } | ||
