diff options
-rw-r--r-- | cmd/podman/ps.go | 5 | ||||
-rw-r--r-- | cmd/podman/utils.go | 29 | ||||
-rw-r--r-- | docs/podman-build.1.md | 14 | ||||
-rw-r--r-- | docs/podman-logs.1.md | 14 | ||||
-rw-r--r-- | docs/podman-run.1.md | 2 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 10 | ||||
-rw-r--r-- | libpod/oci_linux.go | 17 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 5 | ||||
-rw-r--r-- | test/e2e/run_userns_test.go | 15 |
9 files changed, 71 insertions, 40 deletions
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index ad942da2e..20638b424 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -423,7 +423,7 @@ func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Ru return false }, nil case "status": - if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "exited", "unknown"}) { + if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { return nil, errors.Errorf("%s is not a valid status", filterValue) } return func(c *libpod.Container) bool { @@ -431,6 +431,9 @@ func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Ru if err != nil { return false } + if filterValue == "stopped" { + filterValue = "exited" + } state := status.String() if status == libpod.ContainerStateConfigured { state = "created" diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go index 4ec0f8a13..45d081512 100644 --- a/cmd/podman/utils.go +++ b/cmd/podman/utils.go @@ -200,35 +200,6 @@ func getPodsFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpo return pods, lastError } -func getVolumesFromContext(c *cliconfig.PodmanCommand, r *libpod.Runtime) ([]*libpod.Volume, error) { - args := c.InputArgs - var ( - vols []*libpod.Volume - lastError error - err error - ) - - if c.Bool("all") { - vols, err = r.Volumes() - if err != nil { - return nil, errors.Wrapf(err, "unable to get all volumes") - } - } - - for _, i := range args { - vol, err := r.GetVolume(i) - if err != nil { - if lastError != nil { - logrus.Errorf("%q", lastError) - } - lastError = errors.Wrapf(err, "unable to find volume %s", i) - continue - } - vols = append(vols, vol) - } - return vols, lastError -} - //printParallelOutput takes the map of parallel worker results and outputs them // to stdout func printParallelOutput(m map[string]error, errCount int) error { diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md index 42fa9a359..ccc8bd900 100644 --- a/docs/podman-build.1.md +++ b/docs/podman-build.1.md @@ -288,13 +288,21 @@ process. **--pull** -Pull the image if it is not present. If this flag is disabled (with -*--pull=false*) and the image is not present, the image will not be pulled. +When the flag is enabled, attempt to pull the latest image from the registries +listed in registries.conf if a local image does not exist or the image is newer +than the one in storage. Raise an error if the image is not in any listed +registry and is not present locally. + +If the flag is disabled (with *--pull=false*), do not pull the image from the +registry, use only the local version. Raise an error if the image is not +present locally. + Defaults to *true*. **--pull-always** -Pull the image even if a version of the image is already present. +Pull the image from the first registry it is found in as listed in registries.conf. +Raise an error if not found in the registries, even if the image is present locally. **--quiet, -q** diff --git a/docs/podman-logs.1.md b/docs/podman-logs.1.md index 8cd6ad5e7..ce5d890ce 100644 --- a/docs/podman-logs.1.md +++ b/docs/podman-logs.1.md @@ -1,9 +1,11 @@ -% podman-logs(1) +% podman-container-logs(1) ## NAME -podman\-logs - Fetch the logs of one or more containers +podman\-container\-logs (podman\-logs) - Fetch the logs of one or more containers ## SYNOPSIS +**podman** **container** **logs** [*options*] *container* [*container...*] + **podman** **logs** [*options*] *container* [*container...*] ## DESCRIPTION @@ -15,7 +17,11 @@ any logs at the time you execute podman logs **--follow, -f** -Follow log output. Default is false +Follow log output. Default is false. + +Note: If you are following a container which is removed `podman container rm` +or removed on exit `podman run --rm ...`, then there is a chance the the log +file will be removed before `podman logs` reads the final content. **--latest, -l** @@ -86,7 +92,7 @@ podman logs --since 10m myserver ``` ## SEE ALSO -podman(1) +podman(1), podman-run(1), podman-container-rm(1) ## HISTORY February 2018, Updated by Brent Baude <bbaude@redhat.com> diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index cf385717e..b8b3d51f0 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -889,7 +889,7 @@ During container image development, containers often need to write to the image content. Installing packages into /usr, for example. In production, applications seldom need to write to the image. Container applications write to volumes if they need to write to file systems at all. Applications can be -made more secure by running them in read-only mode using the - -read-only switch. +made more secure by running them in read-only mode using the --read-only switch. This protects the containers image from modification. Read only containers may still need to write temporary data. The best way to handle this is to mount tmpfs directories on /run and /tmp. diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 2a7808bdf..c6c9ceb0c 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -203,7 +203,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } // Check if the spec file mounts contain the label Relabel flags z or Z. // If they do, relabel the source directory and then remove the option. - for _, m := range g.Mounts() { + for i := range g.Config.Mounts { + m := &g.Config.Mounts[i] var options []string for _, o := range m.Options { switch o { @@ -219,6 +220,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } m.Options = options + + // If we are using a user namespace, we will use an intermediate + // directory to bind mount volumes + if c.state.UserNSRoot != "" && strings.HasPrefix(m.Source, c.runtime.config.VolumePath) { + newSourceDir := filepath.Join(c.state.UserNSRoot, "volumes") + m.Source = strings.Replace(m.Source, c.runtime.config.VolumePath, newSourceDir, 1) + } } g.SetProcessSelinuxLabel(c.ProcessLabel()) diff --git a/libpod/oci_linux.go b/libpod/oci_linux.go index 2737a641e..f85c5ee62 100644 --- a/libpod/oci_linux.go +++ b/libpod/oci_linux.go @@ -106,6 +106,23 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string, restor if err != nil { return } + + if ctr.state.UserNSRoot != "" { + _, err := os.Stat(ctr.runtime.config.VolumePath) + if err != nil && !os.IsNotExist(err) { + return + } + if err == nil { + volumesTarget := filepath.Join(ctr.state.UserNSRoot, "volumes") + if err := idtools.MkdirAs(volumesTarget, 0700, ctr.RootUID(), ctr.RootGID()); err != nil { + return + } + if err = unix.Mount(ctr.runtime.config.VolumePath, volumesTarget, "none", unix.MS_BIND, ""); err != nil { + return + } + } + } + err = r.createOCIContainer(ctr, cgroupParent, restoreOptions) }() wg.Wait() diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 3b74a65dd..f23dc86dd 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -186,8 +186,11 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. return nil, errors.Wrapf(err, "error creating named volume %q", vol.Source) } ctr.config.Spec.Mounts[i].Source = newVol.MountPoint() + if err := os.Chown(ctr.config.Spec.Mounts[i].Source, ctr.RootUID(), ctr.RootGID()); err != nil { + return nil, errors.Wrapf(err, "cannot chown %q to %d:%d", ctr.config.Spec.Mounts[i].Source, ctr.RootUID(), ctr.RootGID()) + } if err := ctr.copyWithTarFromImage(ctr.config.Spec.Mounts[i].Destination, ctr.config.Spec.Mounts[i].Source); err != nil && !os.IsNotExist(err) { - return nil, errors.Wrapf(err, "Failed to copy content into new volume mount %q", vol.Source) + return nil, errors.Wrapf(err, "failed to copy content into new volume mount %q", vol.Source) } continue } diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index c6c94d2f6..5c38a8950 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -69,6 +69,21 @@ var _ = Describe("Podman UserNS support", func() { Expect(ok).To(BeTrue()) }) + It("podman uidmapping and gidmapping with a volume", func() { + if os.Getenv("SKIP_USERNS") != "" { + Skip("Skip userns tests.") + } + if _, err := os.Stat("/proc/self/uid_map"); err != nil { + Skip("User namespaces not supported.") + } + + session := podmanTest.Podman([]string{"run", "--uidmap=0:1:70000", "--gidmap=0:20000:70000", "-v", "my-foo-volume:/foo:Z", "busybox", "echo", "hello"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + ok, _ := session.GrepString("hello") + Expect(ok).To(BeTrue()) + }) + It("podman uidmapping and gidmapping --net=host", func() { if os.Getenv("SKIP_USERNS") != "" { Skip("Skip userns tests.") |