diff options
| author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-01-14 20:58:34 +0000 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2026-01-21 18:00:26 -0500 |
| commit | 24c604854c6ffe79ac7973e333b2df7f7f82ddd9 (patch) | |
| tree | 95ec7fcdd9f1ac87977ab1d60773ba5178d7a210 /docs | |
| parent | f83a83eb3979e3bc671190650731acf8a5b9ecd3 (diff) | |
| download | meta-virtualization-24c604854c6ffe79ac7973e333b2df7f7f82ddd9.tar.gz | |
image-oci: add multi-layer OCI image support with OCI_LAYERS
Add support for creating multi-layer OCI images with explicit layer
definitions via OCI_LAYERS variable. This enables fine-grained control
over container layer composition.
New variables:
- OCI_LAYER_MODE: Set to "multi" for explicit layer definitions
- OCI_LAYERS: Define layers as "name:type:content" entries
- packages: Install specific packages in a layer
- directories: Copy directories from IMAGE_ROOTFS
- files: Copy specific files from IMAGE_ROOTFS
Package installation uses Yocto's package manager classes (RpmPM,
OpkgPM) for consistency with do_rootfs, rather than calling dnf/opkg
directly.
Example usage:
OCI_LAYER_MODE = "multi"
OCI_LAYERS = "\
base:packages:base-files+base-passwd+netbase \
shell:packages:busybox \
app:packages:curl \
"
This creates a 3-layer OCI image with discrete base, shell, and app
layers that can be shared and cached independently.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/container-bundling.md | 96 |
1 files changed, 85 insertions, 11 deletions
diff --git a/docs/container-bundling.md b/docs/container-bundling.md index fcbb4981..a695a5b8 100644 --- a/docs/container-bundling.md +++ b/docs/container-bundling.md | |||
| @@ -109,31 +109,90 @@ OCI Multi-Layer Images | |||
| 109 | ---------------------- | 109 | ---------------------- |
| 110 | 110 | ||
| 111 | By default, OCI images are single-layer (the entire rootfs in one layer). | 111 | By default, OCI images are single-layer (the entire rootfs in one layer). |
| 112 | To create multi-layer images with shared base layers, set `OCI_BASE_IMAGE`. | 112 | Multi-layer images enable: |
| 113 | - Shared base layers across images | ||
| 114 | - Faster rebuilds via layer caching | ||
| 115 | - Smaller delta updates when only app layer changes | ||
| 113 | 116 | ||
| 114 | ### Single vs Multi-Layer | 117 | ### Layer Modes |
| 115 | 118 | ||
| 116 | # Single layer (default) - full rootfs in one layer | 119 | | Mode | Variable | Layers | Use Case | |
| 117 | inherit image image-oci | 120 | |------|----------|--------|----------| |
| 118 | IMAGE_INSTALL = "base-files busybox myapp" | 121 | | Single | (default) | 1 | Simple containers, backward compat | |
| 122 | | Two-layer | `OCI_BASE_IMAGE` | 2 | Base + app (shared base across images) | | ||
| 123 | | Multi-layer | `OCI_LAYER_MODE="multi"` | 3+ | Fine-grained layers (base, deps, app) | | ||
| 124 | |||
| 125 | ### Two-Layer Mode (OCI_BASE_IMAGE) | ||
| 126 | |||
| 127 | Build on top of another OCI image recipe: | ||
| 119 | 128 | ||
| 120 | # Multi-layer - app layer on top of base layer | 129 | # myapp-container.bb |
| 121 | inherit image image-oci | 130 | inherit image image-oci |
| 122 | OCI_BASE_IMAGE = "container-base" | 131 | OCI_BASE_IMAGE = "container-base" |
| 123 | IMAGE_INSTALL = "base-files busybox myapp" | 132 | IMAGE_INSTALL = "base-files busybox myapp" |
| 124 | 133 | ||
| 125 | ### OCI_BASE_IMAGE | 134 | Result: 2 layers (container-base layer + myapp layer) |
| 126 | 135 | ||
| 127 | Specifies the base image to build on top of: | 136 | | OCI_BASE_IMAGE Value | Description | |
| 128 | 137 | |----------------------|-------------| | |
| 129 | | Value | Description | | ||
| 130 | |-------|-------------| | ||
| 131 | | Recipe name | `"container-base"` - uses OCI output from another recipe | | 138 | | Recipe name | `"container-base"` - uses OCI output from another recipe | |
| 132 | | Absolute path | `"/path/to/oci-dir"` - uses existing OCI layout | | 139 | | Absolute path | `"/path/to/oci-dir"` - uses existing OCI layout | |
| 133 | 140 | ||
| 134 | For external images (docker.io, quay.io), use `container-bundle` with | 141 | For external images (docker.io, quay.io), use `container-bundle` with |
| 135 | `CONTAINER_BUNDLE_DEPLOY = "1"` to fetch and deploy them first. | 142 | `CONTAINER_BUNDLE_DEPLOY = "1"` to fetch and deploy them first. |
| 136 | 143 | ||
| 144 | ### Multi-Layer Mode (OCI_LAYERS) | ||
| 145 | |||
| 146 | Create explicit layers with fine-grained control: | ||
| 147 | |||
| 148 | # app-container-multilayer.bb | ||
| 149 | inherit image image-oci | ||
| 150 | |||
| 151 | OCI_LAYER_MODE = "multi" | ||
| 152 | OCI_LAYERS = "\ | ||
| 153 | base:packages:base-files+base-passwd+netbase \ | ||
| 154 | shell:packages:busybox \ | ||
| 155 | app:packages:curl \ | ||
| 156 | " | ||
| 157 | |||
| 158 | # IMAGE_INSTALL must include all packages to trigger builds | ||
| 159 | IMAGE_INSTALL = "base-files base-passwd netbase busybox curl" | ||
| 160 | |||
| 161 | Result: 3 layers (base, shell, app) | ||
| 162 | |||
| 163 | #### Layer Definition Format | ||
| 164 | |||
| 165 | name:type:content | ||
| 166 | |||
| 167 | | Type | Content Format | Description | | ||
| 168 | |------|----------------|-------------| | ||
| 169 | | `packages` | `pkg1+pkg2+pkg3` | Install packages (use + delimiter) | | ||
| 170 | | `directories` | `/path1+/path2` | Copy directories from IMAGE_ROOTFS | | ||
| 171 | | `files` | `/file1+/file2` | Copy specific files from IMAGE_ROOTFS | | ||
| 172 | |||
| 173 | #### Example Recipes | ||
| 174 | |||
| 175 | **Three-layer with explicit packages:** | ||
| 176 | ```bitbake | ||
| 177 | OCI_LAYER_MODE = "multi" | ||
| 178 | OCI_LAYERS = "\ | ||
| 179 | base:packages:base-files+base-passwd+netbase \ | ||
| 180 | python:packages:python3+python3-pip \ | ||
| 181 | app:directories:/opt/myapp \ | ||
| 182 | " | ||
| 183 | IMAGE_INSTALL = "base-files base-passwd netbase python3 python3-pip myapp" | ||
| 184 | ``` | ||
| 185 | |||
| 186 | **Two-layer with base image + multi-layer app:** | ||
| 187 | ```bitbake | ||
| 188 | OCI_BASE_IMAGE = "container-base" | ||
| 189 | OCI_LAYER_MODE = "multi" | ||
| 190 | OCI_LAYERS = "\ | ||
| 191 | deps:packages:python3+python3-pip \ | ||
| 192 | app:directories:/opt/myapp \ | ||
| 193 | " | ||
| 194 | ``` | ||
| 195 | |||
| 137 | ### OCI_IMAGE_CMD vs OCI_IMAGE_ENTRYPOINT | 196 | ### OCI_IMAGE_CMD vs OCI_IMAGE_ENTRYPOINT |
| 138 | 197 | ||
| 139 | # CMD (default) - replaced when user passes arguments | 198 | # CMD (default) - replaced when user passes arguments |
| @@ -149,6 +208,21 @@ For external images (docker.io, quay.io), use `container-bundle` with | |||
| 149 | 208 | ||
| 150 | Use CMD for base images (flexible). Use ENTRYPOINT for wrapper tools. | 209 | Use CMD for base images (flexible). Use ENTRYPOINT for wrapper tools. |
| 151 | 210 | ||
| 211 | ### Verifying Layer Count | ||
| 212 | |||
| 213 | # Check layer count with skopeo | ||
| 214 | skopeo inspect oci:tmp/deploy/images/qemux86-64/myapp-latest-oci | jq '.Layers | length' | ||
| 215 | |||
| 216 | ### Testing Multi-Layer OCI | ||
| 217 | |||
| 218 | cd /opt/bruce/poky/meta-virtualization | ||
| 219 | |||
| 220 | # Quick tests (no builds) | ||
| 221 | pytest tests/test_multilayer_oci.py -v -k "not slow" | ||
| 222 | |||
| 223 | # Full tests (with builds) | ||
| 224 | pytest tests/test_multilayer_oci.py -v --poky-dir /opt/bruce/poky | ||
| 225 | |||
| 152 | 226 | ||
| 153 | Using BUNDLED_CONTAINERS | 227 | Using BUNDLED_CONTAINERS |
| 154 | ------------------------ | 228 | ------------------------ |
