diff --git a/docs/source/markdown/podman-systemd.unit.5.md b/docs/source/markdown/podman-systemd.unit.5.md index 258b123a4c..d959f44d93 100644 --- a/docs/source/markdown/podman-systemd.unit.5.md +++ b/docs/source/markdown/podman-systemd.unit.5.md @@ -188,6 +188,14 @@ This key can be listed multiple times. If enabled (which is the default), this disables the container processes from gaining additional privileges via things like setuid and file capabilities. +#### `Rootfs=` + +The rootfs to use for the container. Rootfs points to a directory on the system that contains the content to be run within the container. This option conflicts with the `Image` option. + +The format of the rootfs is the same as when passed to `podman run --rootfs`, so it supports ovelay mounts as well. + +Note: On SELinux systems, the rootfs needs the correct label, which is by default unconfined_u:object_r:container_file_t:s0. + #### `Notify=` (defaults to `no`) By default, Podman is run in such a way that the systemd startup notify command is handled by diff --git a/pkg/systemd/quadlet/quadlet.go b/pkg/systemd/quadlet/quadlet.go index d138a0dd15..3c7f6e2e76 100644 --- a/pkg/systemd/quadlet/quadlet.go +++ b/pkg/systemd/quadlet/quadlet.go @@ -45,6 +45,7 @@ const ( KeyRemapUID = "RemapUid" KeyRemapGID = "RemapGid" KeyRemapUIDSize = "RemapUidSize" + KeyRootfs = "Rootfs" KeyNotify = "Notify" KeyExposeHostPort = "ExposeHostPort" KeyPublishPort = "PublishPort" @@ -96,6 +97,7 @@ var ( KeyRemapUID: true, KeyRemapGID: true, KeyRemapUIDSize: true, + KeyRootfs: true, KeyNotify: true, KeyExposeHostPort: true, KeyPublishPort: true, @@ -239,9 +241,14 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile // Rename old Container group to x-Container so that systemd ignores it service.RenameGroup(ContainerGroup, XContainerGroup) - image, ok := container.Lookup(ContainerGroup, KeyImage) - if !ok || len(image) == 0 { - return nil, fmt.Errorf("no Image key specified") + // One image or rootfs must be specified for the container + image, _ := container.Lookup(ContainerGroup, KeyImage) + rootfs, _ := container.Lookup(ContainerGroup, KeyRootfs) + if len(image) == 0 && len(rootfs) == 0 { + return nil, fmt.Errorf("no Image or Rootfs key specified") + } + if len(image) > 0 && len(rootfs) > 0 { + return nil, fmt.Errorf("the Image And Rootfs keys conflict can not be specified together") } containerName, ok := container.Lookup(ContainerGroup, KeyContainerName) @@ -486,7 +493,11 @@ func ConvertContainer(container *parser.UnitFile, isUser bool) (*parser.UnitFile podmanArgs := container.LookupAllArgs(ContainerGroup, KeyPodmanArgs) podman.add(podmanArgs...) - podman.add(image) + if len(image) > 0 { + podman.add(image) + } else { + podman.add("--rootfs", rootfs) + } execArgs, ok := container.LookupLastArgs(ContainerGroup, KeyExec) if ok { diff --git a/test/e2e/quadlet/noimage.container b/test/e2e/quadlet/noimage.container index 909c8c54a1..d71951c3c9 100644 --- a/test/e2e/quadlet/noimage.container +++ b/test/e2e/quadlet/noimage.container @@ -1,4 +1,4 @@ ## assert-failed -## assert-stderr-contains "no Image key specified" +## assert-stderr-contains "no Image or Rootfs key specified" [Container] diff --git a/test/e2e/quadlet/rootfs.container b/test/e2e/quadlet/rootfs.container new file mode 100644 index 0000000000..2f5a2ad0ff --- /dev/null +++ b/test/e2e/quadlet/rootfs.container @@ -0,0 +1,4 @@ +## assert-podman-final-args "--rootfs" "/var/lib/foobar" + +[Container] +Rootfs=/var/lib/foobar diff --git a/test/e2e/quadlet_test.go b/test/e2e/quadlet_test.go index 7cd1a31a06..a778e4ddc8 100644 --- a/test/e2e/quadlet_test.go +++ b/test/e2e/quadlet_test.go @@ -460,6 +460,7 @@ var _ = Describe("quadlet system generator", func() { Entry("noimage.container", "noimage.container"), Entry("notify.container", "notify.container"), Entry("oneshot.container", "oneshot.container"), + Entry("rootfs.container", "rootfs.container"), Entry("other-sections.container", "other-sections.container"), Entry("podmanargs.container", "podmanargs.container"), Entry("ports.container", "ports.container"), diff --git a/test/system/252-quadlet.bats b/test/system/252-quadlet.bats index 8feed02c50..d130ee962f 100644 --- a/test/system/252-quadlet.bats +++ b/test/system/252-quadlet.bats @@ -406,4 +406,23 @@ EOF run_podman rmi $(pause_image) } +@test "quadlet - rootfs" { + skip_if_no_selinux + skip_if_rootless + local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).container + cat > $quadlet_file <