[meta-virtualization][PATCH 5/7] recipes-containers/images: add app-container-nginx

Tim Orling <[email protected]> Fri, 29 May 2026 18:31:06 -0700
Newsgroups org.yoctoproject.lists.meta-virtualization
Message-ID <4b1e72e8de33b35f7e8b8c66bc0ef8820c722db1.1780104071.git.tim.orling@konsulko.com>
Add OCI container image recipe for the NGINX web server. The image
uses multi-layer mode with separate base, nginx packages, nginx
runtime directories, and nginx log file layers. Exposes the standard
HTTP port (80) and launches nginx with 'daemon off' so it stays in
the foreground as PID 1 and logs to stderr.

Add ROOTFS_POSTPROCESS fixups to create the runtime directories
nginx expects: /var/volatile/{tmp,log}, /var/log/nginx (resolved
explicitly to guarantee inclusion in the container layer regardless
of /var/log symlink ordering), and /run/nginx for nginx's compiled-in
temp paths (client_body_temp, proxy_temp, etc.) which are not created
by any package. Also create empty /var/log/nginx/{access,error}.log
to avoid do_image_oci warnings.

Inherit container-nonroot-user with NONROOT_USER = "nginx" to run with
UID 65532 by default. Set PACKAGECONFIG:pn-app-container-nginx = "dev"
in local.conf or distro/image config to run as 'root'.

Add SKIP_RECIPE and comment to layer.conf since nginx requires
meta-webserver.

Signed-off-by: Tim Orling <[email protected]>
---
 conf/layer.conf                               |  1 +
 .../images/app-container-nginx.bb             | 77 +++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 recipes-containers/images/app-container-nginx.bb

diff --git a/conf/layer.conf b/conf/layer.conf
index 2a4a4c91..6ea8ccf8 100644
--- a/conf/layer.conf
+++ b/conf/layer.conf
@@ -33,6 +33,7 @@ LAYERDEPENDS_virtualization-layer = " \
 # webserver:
 # - naigos requires apache2
 # - cockpit-machines requires cockpit
+# - app-container-nginx requires nginx
 LAYERRECOMMENDS_virtualization-layer = " \
     webserver \
     selinux \
diff --git a/recipes-containers/images/app-container-nginx.bb b/recipes-containers/images/app-container-nginx.bb
new file mode 100644
index 00000000..09844376
--- /dev/null
+++ b/recipes-containers/images/app-container-nginx.bb
@@ -0,0 +1,77 @@
+SUMMARY = "Base NGINX container image for development"
+DESCRIPTION = "OCI container with NGINX web server."
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
+
+# Multi-layer mode: create explicit layers instead of single rootfs layer
+OCI_LAYER_MODE = "multi"
+
+# Optional 'dev' mode:
+#   - runs the container as root (UID 0)
+# Enable with: PACKAGECONFIG:pn-app-container-nginx = "dev"
+PACKAGECONFIG ??= ""
+PACKAGECONFIG[dev] = ""
+NONROOT_USER = "nginx"
+
+OCI_IMAGE_APP_RECIPE = "nginx"
+
+# Define layers: each layer contains specific packages
+# Format: "name:type:content" where content uses + as delimiter for multiple items
+OCI_LAYERS = "\
+    base:packages:base-files+base-passwd+netbase \
+    nginx:packages:nginx \
+    nginx-dirs:directories:${localstatedir}/log/nginx+/run/nginx+${localstatedir}/volatile/tmp+${localstatedir}/volatile/log \
+    nginx-files:files:${localstatedir}/log/nginx/access.log+${localstatedir}/log/nginx/error.log \
+"
+# Use CMD so `docker run image /bin/sh` works as expected
+OCI_IMAGE_CMD = ""
+
+IMAGE_FSTYPES = "container oci"
+inherit image
+inherit image-oci
+inherit container-nonroot-user
+
+IMAGE_FEATURES = ""
+IMAGE_LINGUAS = ""
+NO_RECOMMENDATIONS = "1"
+
+IMAGE_INSTALL = " \
+       base-files \
+       base-passwd \
+       netbase \
+       nginx \
+"
+
+# Allow build with or without a specific kernel
+IMAGE_CONTAINER_NO_DUMMY = "1"
+
+# Workaround /var/volatile for now
+ROOTFS_POSTPROCESS_COMMAND:append = " rootfs_fixup_var_volatile ; "
+rootfs_fixup_var_volatile () {
+    install -m 1777 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/tmp
+    install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/log
+    install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/volatile/log/nginx
+
+    # Fix do_image_oci warnings
+    # OCI: File not found in IMAGE_ROOTFS: /var/log/nginx/access.log
+    touch ${IMAGE_ROOTFS}/${localstatedir}/volatile/log/nginx/access.log
+    touch ${IMAGE_ROOTFS}/${localstatedir}/volatile/log/nginx/error.log
+
+    # nginx opens the compiled-in error_log path before reading -c config.
+    # /var/log is typically a symlink to /var/volatile/log in a Yocto rootfs,
+    # so create the target path explicitly to guarantee the directory lands in
+    # the container layer regardless of symlink resolution order.
+    install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/log
+    install -m 755 -d ${IMAGE_ROOTFS}/${localstatedir}/log/nginx
+
+    # nginx's compiled-in temp paths (client_body_temp, proxy_temp, etc.) all
+    # live under /run/nginx, which is not created by any package.
+    install -m 755 -d ${IMAGE_ROOTFS}/run/nginx
+}
+
+OCI_IMAGE_ENTRYPOINT = "/usr/sbin/nginx"
+OCI_IMAGE_ENTRYPOINT_ARGS = "-g 'daemon off; error_log stderr notice;'"
+OCI_IMAGE_PORTS = "80/tcp"
+OCI_IMAGE_TAG = "latest"
+
+SKIP_RECIPE[app-container-nginx] ?= "${@bb.utils.contains('BBFILE_COLLECTIONS', 'webserver', '', 'Depends on meta-webserver which is not included', d)}"
-- 
2.54.0