diff options
-rwxr-xr-x | API.md | 2 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | cmd/podman/cliconfig/defaults.go | 5 | ||||
-rw-r--r-- | cmd/podman/common.go | 6 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 14 | ||||
-rw-r--r-- | cmd/podman/shared/intermediate.go | 2 | ||||
-rw-r--r-- | cmd/podman/shared/intermediate_varlink.go | 5 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 2 | ||||
-rw-r--r-- | docs/podman-create.1.md | 12 | ||||
-rw-r--r-- | docs/podman-derivative-api | 64 | ||||
-rw-r--r-- | docs/podman-run.1.md | 12 | ||||
-rw-r--r-- | libpod/info.go | 13 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 8 | ||||
-rw-r--r-- | pkg/rootless/rootless_unsupported.go | 5 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 3 | ||||
-rw-r--r-- | pkg/spec/spec.go | 10 | ||||
-rw-r--r-- | test/e2e/start_test.go | 4 | ||||
-rw-r--r-- | test/e2e/systemd_test.go | 2 | ||||
-rw-r--r-- | troubleshooting.md | 2 |
19 files changed, 141 insertions, 35 deletions
@@ -1591,7 +1591,7 @@ subgidname [?string](#?string) sysctl [?[]string](#?[]string) -systemd [?bool](#?bool) +systemd [?string](#?string) tmpfs [?[]string](#?[]string) @@ -438,7 +438,10 @@ install.systemd: install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.socket ${DESTDIR}${SYSTEMDDIR}/io.podman.socket install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.socket ${DESTDIR}${USERSYSTEMDDIR}/io.podman.socket install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.service ${DESTDIR}${SYSTEMDDIR}/io.podman.service - install ${SELINUXOPT} -m 644 contrib/varlink/io.podman.service ${DESTDIR}${USERSYSTEMDDIR}/io.podman.service + install ${SELINUXOPT} -d ${DESTDIR}${USERSYSTEMDDIR} + # User units are ordered differently, we can't make the *system* multi-user.target depend on a user unit. + # For user units the default.target that's the default is fine. + sed -e 's,^WantedBy=.*,WantedBy=default.target,' < contrib/varlink/io.podman.service > ${DESTDIR}${USERSYSTEMDDIR}/io.podman.service install ${SELINUXOPT} -m 644 contrib/varlink/podman.conf ${DESTDIR}${TMPFILESDIR}/podman.conf uninstall: diff --git a/cmd/podman/cliconfig/defaults.go b/cmd/podman/cliconfig/defaults.go index d5dae0874..ce695d153 100644 --- a/cmd/podman/cliconfig/defaults.go +++ b/cmd/podman/cliconfig/defaults.go @@ -1,10 +1,5 @@ package cliconfig -const ( - // DefaultSystemD value - DefaultSystemD bool = true -) - var ( // DefaultHealthCheckInterval default value DefaultHealthCheckInterval = "30s" diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 2a3f8f3ad..e93586b62 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -455,9 +455,9 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "sysctl", []string{}, "Sysctl options (default [])", ) - createFlags.Bool( - "systemd", cliconfig.DefaultSystemD, - "Run container in systemd mode if the command executable is systemd or init", + createFlags.String( + "systemd", "true", + `Run container in systemd mode ("true"|"false"|"always" (default "true")`, ) createFlags.StringArray( "tmpfs", []string{}, diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 9020613c5..7c56db8db 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -662,9 +662,17 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. return nil, errors.Errorf("invalid image-volume type %q. Pick one of bind, tmpfs, or ignore", c.String("image-volume")) } - var systemd bool - if command != nil && c.Bool("systemd") && ((filepath.Base(command[0]) == "init") || (filepath.Base(command[0]) == "systemd")) { - systemd = true + systemd := c.String("systemd") == "always" + if !systemd && command != nil { + x, err := strconv.ParseBool(c.String("systemd")) + if err != nil { + return nil, errors.Wrapf(err, "cannot parse bool %s", c.String("systemd")) + } + if x && (command[0] == "/usr/sbin/init" || (filepath.Base(command[0]) == "systemd")) { + systemd = true + } + } + if systemd { if signalString == "" { stopSignal, err = signal.ParseSignal("RTMIN+3") if err != nil { diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go index cccdd1bea..0f71dc087 100644 --- a/cmd/podman/shared/intermediate.go +++ b/cmd/podman/shared/intermediate.go @@ -449,7 +449,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes m["subgidname"] = newCRString(c, "subgidname") m["subuidname"] = newCRString(c, "subuidname") m["sysctl"] = newCRStringSlice(c, "sysctl") - m["systemd"] = newCRBool(c, "systemd") + m["systemd"] = newCRString(c, "systemd") m["tmpfs"] = newCRStringArray(c, "tmpfs") m["tty"] = newCRBool(c, "tty") m["uidmap"] = newCRStringSlice(c, "uidmap") diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go index 9dbf83950..c95470a72 100644 --- a/cmd/podman/shared/intermediate_varlink.go +++ b/cmd/podman/shared/intermediate_varlink.go @@ -152,7 +152,7 @@ func (g GenericCLIResults) MakeVarlink() iopodman.Create { Subuidname: StringToPtr(g.Find("subuidname")), Subgidname: StringToPtr(g.Find("subgidname")), Sysctl: StringSliceToPtr(g.Find("sysctl")), - Systemd: BoolToPtr(g.Find("systemd")), + Systemd: StringToPtr(g.Find("systemd")), Tmpfs: StringSliceToPtr(g.Find("tmpfs")), Tty: BoolToPtr(g.Find("tty")), Uidmap: StringSliceToPtr(g.Find("uidmap")), @@ -321,6 +321,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { var memSwapDefault int64 = -1 netModeDefault := "bridge" + systemdDefault := "true" if rootless.IsRootless() { netModeDefault = "slirp4netns" } @@ -409,7 +410,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { m["subgidname"] = stringFromVarlink(opts.Subgidname, "subgidname", nil) m["subuidname"] = stringFromVarlink(opts.Subuidname, "subuidname", nil) m["sysctl"] = stringSliceFromVarlink(opts.Sysctl, "sysctl", nil) - m["systemd"] = boolFromVarlink(opts.Systemd, "systemd", cliconfig.DefaultSystemD) + m["systemd"] = stringFromVarlink(opts.Systemd, "systemd", &systemdDefault) m["tmpfs"] = stringSliceFromVarlink(opts.Tmpfs, "tmpfs", nil) m["tty"] = boolFromVarlink(opts.Tty, "tty", false) m["uidmap"] = stringSliceFromVarlink(opts.Uidmap, "uidmap", nil) diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 2408dc80c..13e8394fb 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -363,7 +363,7 @@ type Create ( subuidname: ?string, subgidname: ?string, sysctl: ?[]string, - systemd: ?bool, + systemd: ?string, tmpfs: ?[]string, tty: ?bool, uidmap: ?[]string, diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 46fa4fcd4..35602f97b 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -710,12 +710,18 @@ Network Namespace - current sysctls allowed: Note: if you use the --network=host option these sysctls will not be allowed. -**--systemd**=*true|false* +**--systemd**=*true|false|always* Run container in systemd mode. The default is *true*. -If the command you running inside of the container is systemd or init, podman -will setup tmpfs mount points in the following directories: +The value *always* enforces the systemd mode is enforced without +looking at the executable name. Otherwise, if set to true and the +command you are running inside the container is systemd or +/usr/sbin/init. + +If the command you are running inside of the container is systemd or +/usr/sbin/init, Podman will setup tmpfs mount points in the following +directories: /run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal diff --git a/docs/podman-derivative-api b/docs/podman-derivative-api new file mode 100644 index 000000000..1b6153df5 --- /dev/null +++ b/docs/podman-derivative-api @@ -0,0 +1,64 @@ +.TH How to use libpod for custom/derivative projects +.PP +libpod today is a Golang library and a CLI. The choice of interface you make has advantages and disadvantages. + +.SH Running as a subprocess +.PP +Advantages: + +.RS +.IP \(bu 2 +Many commands output JSON +.IP \(bu 2 +Works with languages other than Golang +.IP \(bu 2 +Easy to get started + +.RE + +.PP +Disadvantages: + +.RS +.IP \(bu 2 +Error handling is harder +.IP \(bu 2 +May be slower +.IP \(bu 2 +Can't hook into or control low\-level things like how images are pulled + +.RE + +.SH Vendoring into a Go project +.PP +Advantages: + +.RS +.IP \(bu 2 +Significant power and control + +.RE + +.PP +Disadvantages: + +.RS +.IP \(bu 2 +You are now on the hook for container runtime security updates (partially, \fB\fCrunc\fR/\fB\fCcrun\fR are separate) +.IP \(bu 2 +Binary size +.IP \(bu 2 +Potential skew between multiple libpod versions operating on the same storage can cause problems + +.RE + +.SH Varlink +.PP +Some code exists for this; splits the difference. Future uncertain. + +.SH Making the choice +.PP +A good question to ask first is: Do you want users to be able to use \fB\fCpodman\fR to manipulate the containers created by your project? +If so, that makes it more likely that you want to run \fB\fCpodman\fR as a subprocess. If you want a separate image store and a fundamentally +different experience; if what you're doing with containers is quite different from those created by the \fB\fCpodman\fR CLI, +that may drive you towards vendoring. diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index dfc634288..e255119d7 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -747,12 +747,18 @@ Network Namespace - current sysctls allowed: Note: if you use the `--network=host` option these sysctls will not be allowed. -**--systemd**=*true|false* +**--systemd**=*true|false|always* Run container in systemd mode. The default is *true*. -If the command you are running inside of the container is systemd or init, Podman -will setup tmpfs mount points in the following directories: +The value *always* enforces the systemd mode is enforced without +looking at the executable name. Otherwise, if set to true and the +command you are running inside the container is systemd or +/usr/sbin/init. + +If the command you are running inside of the container is systemd or +/usr/sbin/init, Podman will setup tmpfs mount points in the following +directories: /run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal diff --git a/libpod/info.go b/libpod/info.go index 297086ebb..6caa87038 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -69,6 +69,18 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { program["Package"] = packageVersion(path) info["slirp4netns"] = program } + uidmappings, err := rootless.ReadMappingsProc("/proc/self/uid_map") + if err != nil { + return nil, errors.Wrapf(err, "error reading uid mappings") + } + gidmappings, err := rootless.ReadMappingsProc("/proc/self/gid_map") + if err != nil { + return nil, errors.Wrapf(err, "error reading gid mappings") + } + idmappings := make(map[string]interface{}) + idmappings["uidmap"] = uidmappings + idmappings["gidmap"] = gidmappings + info["IDMappings"] = idmappings } info["OCIRuntime"] = map[string]interface{}{ "path": r.defaultOCIRuntime.path, @@ -128,6 +140,7 @@ func (r *Runtime) hostInfo() (map[string]interface{}, error) { } info["hostname"] = host info["eventlogger"] = r.eventer.String() + return info, nil } diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 05d641383..99307e8c4 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -431,12 +431,14 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, if err != nil { return false, -1, errors.Wrapf(err, "cannot write setgroups file") } + logrus.Debugf("write setgroups file exited with 0") uidMap := fmt.Sprintf("/proc/%d/uid_map", pid) err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Geteuid())), 0666) if err != nil { return false, -1, errors.Wrapf(err, "cannot write uid_map") } + logrus.Debugf("write uid_map exited with 0") } gidsMapped := false @@ -602,7 +604,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st return joinUserAndMountNS(uint(pausePid), pausePidPath) } -func readMappingsProc(path string) ([]idtools.IDMap, error) { +func ReadMappingsProc(path string) ([]idtools.IDMap, error) { file, err := os.Open(path) if err != nil { return nil, errors.Wrapf(err, "cannot open %s", path) @@ -668,7 +670,7 @@ func ConfigurationMatches() (bool, error) { return false, err } - currentUIDs, err := readMappingsProc("/proc/self/uid_map") + currentUIDs, err := ReadMappingsProc("/proc/self/uid_map") if err != nil { return false, err } @@ -677,7 +679,7 @@ func ConfigurationMatches() (bool, error) { return false, err } - currentGIDs, err := readMappingsProc("/proc/self/gid_map") + currentGIDs, err := ReadMappingsProc("/proc/self/gid_map") if err != nil { return false, err } diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go index ddd9182b0..ce488f364 100644 --- a/pkg/rootless/rootless_unsupported.go +++ b/pkg/rootless/rootless_unsupported.go @@ -65,3 +65,8 @@ func ConfigurationMatches() (bool, error) { func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) { return nil, nil, errors.New("this function is not supported on this os") } + +// ReadMappingsProc returns the uid_map and gid_map +func ReadMappingsProc(path string) ([]idtools.IDMap, error) { + return nil, nil +} diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index a65263b7d..3685450f0 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -195,8 +195,7 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l if c.Interactive { options = append(options, libpod.WithStdin()) } - if c.Systemd && (strings.HasSuffix(c.Command[0], "init") || - strings.HasSuffix(c.Command[0], "systemd")) { + if c.Systemd { options = append(options, libpod.WithSystemd()) } if c.Name != "" { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 57c6e8da7..8f00d3270 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -302,8 +302,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM // RESOURCES - PIDS if config.Resources.PidsLimit > 0 { - // if running on rootless on a cgroupv1 machine, pids limit is - // not supported. If the value is still the default + // if running on rootless on a cgroupv1 machine or using the cgroupfs manager, pids + // limit is not supported. If the value is still the default // then ignore the settings. If the caller asked for a // non-default, then try to use it. setPidLimit := true @@ -312,7 +312,11 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM if err != nil { return nil, err } - if !cgroup2 && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() { + runtimeConfig, err := runtime.GetConfig() + if err != nil { + return nil, err + } + if (!cgroup2 || runtimeConfig.CgroupManager != libpod.SystemdCgroupsManager) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() { setPidLimit = false } } diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index 06ab6aacd..13f14183b 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -110,7 +110,7 @@ var _ = Describe("Podman start", func() { start.WaitWithDefaultTimeout() Expect(start.ExitCode()).Should(BeNumerically(">", 0)) - Eventually(podmanTest.NumberOfContainers(), defaultWaitTimeout).Should(BeZero()) + Eventually(podmanTest.NumberOfContainers(), defaultWaitTimeout, 3.0).Should(BeZero()) }) It("podman failed to start without --rm should NOT delete the container", func() { @@ -122,7 +122,7 @@ var _ = Describe("Podman start", func() { start.WaitWithDefaultTimeout() Expect(start.ExitCode()).Should(BeNumerically(">", 0)) - Eventually(podmanTest.NumberOfContainers(), defaultWaitTimeout).Should(Equal(1)) + Eventually(podmanTest.NumberOfContainers(), defaultWaitTimeout, 3.0).Should(Equal(1)) }) It("podman start --sig-proxy should not work without --attach", func() { diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index 02778d493..9ec48ba00 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -94,7 +94,7 @@ WantedBy=multi-user.target Expect(pull.ExitCode()).To(Equal(0)) ctrName := "testSystemd" - run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", systemdImage, "init"}) + run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", systemdImage, "/usr/sbin/init"}) run.WaitWithDefaultTimeout() Expect(run.ExitCode()).To(Equal(0)) ctrID := run.OutputToString() diff --git a/troubleshooting.md b/troubleshooting.md index 89c850356..6fed719f7 100644 --- a/troubleshooting.md +++ b/troubleshooting.md @@ -142,7 +142,7 @@ If you are using a useradd command within a Dockerfile with a large UID/GID, it #### Solution -If the entry in the Dockerfile looked like: RUN useradd -u 99999000 -g users newuser then add the `--log-no-init` parameter to change it to: `RUN useradd --log-no-init -u 99999000 -g users newuser`. This option tells useradd to stop creating the lastlog file. +If the entry in the Dockerfile looked like: RUN useradd -u 99999000 -g users newuser then add the `--no-log-init` parameter to change it to: `RUN useradd --no-log-init -u 99999000 -g users newuser`. This option tells useradd to stop creating the lastlog file. ### 7) Permission denied when running Podman commands |