From 3bf6e77e079accc8d20d81ffc8fea253dcee4cfb Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 30 Jan 2026 14:23:32 -0500 Subject: [PATCH] devenv: Improve nested container support The default containers.conf includes net.ipv4.ping_group_range=0 0 which fails in nested containers because /proc/sys is read-only. This causes 'podman build' to fail with: open `/proc/sys/net/ipv4/ping_group_range`: Read-only file system This matches the approach used by the official quay.io/podman/stable image (containers/image_build) which sets default_sysctls = [] in its podman-containers.conf. Assisted-by: OpenCode (claude-opus-4-5@20251101) Signed-off-by: Colin Walters --- devenv/README.md | 31 +++++++++++++++++++++++++++++++ devenv/userns-setup | 36 +++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/devenv/README.md b/devenv/README.md index e7023fa..9802e17 100644 --- a/devenv/README.md +++ b/devenv/README.md @@ -15,6 +15,37 @@ base, but this helps prove out the general case of "src != target" that is a philosophy of bootc (and containers in general) as well as just helping prepare/motivate for bootc-on-Debian. +## Nested container support + +This image supports running `podman` and `podman build` inside the container +(podman-in-podman). The `userns-setup` script configures the environment at +container startup. + +### Reference: quay.io/podman/stable + +Our nested container configuration is based on the official +[quay.io/podman/stable](https://github.com/containers/image_build/tree/main/podman) +image. Key differences: + +| Feature | quay.io/podman/stable | bootc-devenv | +|---------|----------------------|--------------| +| **default_sysctls** | `[]` | `[]` | +| **cgroups** | `"disabled"` | `"disabled"` (constrained) / `"no-conmon"` (full) | +| **cgroup_manager** | `"cgroupfs"` | `"cgroupfs"` | +| **netns/userns/ipcns/utsns/cgroupns** | `"host"` for all | `utsns = "host"` (constrained only) | +| **BUILDAH_ISOLATION** | `chroot` (env var) | Not set (uses OCI default) | +| **subuid/subgid** | Hardcoded for `podman` user | Dynamically calculated based on available UID range | +| **storage** | Modified storage.conf for fuse-overlayfs | VOLUME mounts avoid overlay-on-overlay | + +### Constrained vs full UID namespace + +The `userns-setup` script detects whether we're running in a constrained UID +namespace (typical for rootless podman, GitHub Codespaces, etc.) and adjusts: + +- **Full namespace** (>100k UIDs): Uses default subuid/subgid, `cgroups = "no-conmon"` +- **Constrained namespace** (<100k UIDs): Dynamically calculates subuid/subgid + ranges, uses `cgroups = "disabled"` and `utsns = "host"` + ## Building locally See the `Justfile`, but it's just a thin wrapper around a default diff --git a/devenv/userns-setup b/devenv/userns-setup index 2858c05..36c6088 100644 --- a/devenv/userns-setup +++ b/devenv/userns-setup @@ -7,6 +7,9 @@ This handles: - /dev/kvm permissions - subuid/subgid configuration for constrained UID namespaces - containers.conf configuration for nested operation + +Reference: quay.io/podman/stable image configuration + https://github.com/containers/image_build/tree/main/podman """ import argparse @@ -169,28 +172,31 @@ def configure_containers_conf() -> None: is_constrained, _ = detect_constrained_namespace() + conf_dir = Path("/etc/containers") + conf_dir.mkdir(parents=True, exist_ok=True) + conf_path = conf_dir / "containers.conf" + if not is_constrained: - # Full namespace - just update the shipped config - conf_path = Path("/usr/share/containers/containers.conf") - if conf_path.exists(): - content = conf_path.read_text() - content = content.replace("#cgroups =", 'cgroups = "no-conmon" #') - content = content.replace("#cgroup_manager =", 'cgroup_manager = "cgroupfs" #') - conf_path.write_text(content) + header = "# Generated for nested container support" + container_settings = 'cgroups = "no-conmon"' else: - # Constrained namespace - create full config for nested operation - conf_dir = Path("/etc/containers") - conf_dir.mkdir(parents=True, exist_ok=True) - conf_path = conf_dir / "containers.conf" - conf_path.write_text("""\ -# Generated for nested container support in constrained UID namespace + header = "# Generated for nested container support in constrained UID namespace" + container_settings = 'cgroups = "disabled"\nutsns = "host"' + + conf_path.write_text(f"""\ +{header} +# Reference: https://github.com/containers/image_build/tree/main/podman [containers] -cgroups = "disabled" -utsns = "host" +# Disable default sysctls - /proc/sys is read-only in nested containers +# (specifically net.ipv4.ping_group_range causes "Read-only file system" errors) +# See: https://github.com/containers/common/blob/main/pkg/config/containers.conf +default_sysctls = [] +{container_settings} [engine] cgroup_manager = "cgroupfs" """) + if is_constrained: print("Configured containers.conf for constrained UID namespace")