浏览代码

Merge pull request #20017 from calavera/expose_volumes_in_ps

Add mounts to docker ps.
Sebastiaan van Stijn 9 年之前
父节点
当前提交
034a1a8dfd

+ 15 - 0
api/client/formatter/custom.go

@@ -31,6 +31,7 @@ const (
 	repositoryHeader   = "REPOSITORY"
 	tagHeader          = "TAG"
 	digestHeader       = "DIGEST"
+	mountsHeader       = "MOUNTS"
 )
 
 type containerContext struct {
@@ -142,6 +143,20 @@ func (c *containerContext) Label(name string) string {
 	return c.c.Labels[name]
 }
 
+func (c *containerContext) Mounts() string {
+	c.addHeader(mountsHeader)
+
+	var mounts []string
+	for _, m := range c.c.Mounts {
+		name := m.Name
+		if c.trunc {
+			name = stringutils.Truncate(name, 15)
+		}
+		mounts = append(mounts, name)
+	}
+	return strings.Join(mounts, ",")
+}
+
 type imageContext struct {
 	baseSubContext
 	trunc  bool

+ 23 - 0
daemon/list.go

@@ -9,6 +9,7 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/image"
+	"github.com/docker/docker/volume"
 	"github.com/docker/engine-api/types"
 	"github.com/docker/engine-api/types/filters"
 	networktypes "github.com/docker/engine-api/types/network"
@@ -306,6 +307,27 @@ func includeContainerInList(container *container.Container, ctx *listContext) it
 		return excludeContainer
 	}
 
+	if ctx.filters.Include("volume") {
+		volumesByName := make(map[string]*volume.MountPoint)
+		for _, m := range container.MountPoints {
+			volumesByName[m.Name] = m
+		}
+
+		volumeExist := fmt.Errorf("volume mounted in container")
+		err := ctx.filters.WalkValues("volume", func(value string) error {
+			if _, exist := container.MountPoints[value]; exist {
+				return volumeExist
+			}
+			if _, exist := volumesByName[value]; exist {
+				return volumeExist
+			}
+			return nil
+		})
+		if err != volumeExist {
+			return excludeContainer
+		}
+	}
+
 	if ctx.ancestorFilter {
 		if len(ctx.images) == 0 {
 			return excludeContainer
@@ -419,6 +441,7 @@ func (daemon *Daemon) transformContainer(container *container.Container, ctx *li
 		newC.SizeRootFs = sizeRootFs
 	}
 	newC.Labels = container.Config.Labels
+	newC.Mounts = addMountPoints(container)
 
 	return newC, nil
 }

+ 1 - 0
docs/reference/api/docker_remote_api.md

@@ -116,6 +116,7 @@ This section lists each version from latest to oldest.  Each listing includes a
 [Docker Remote API v1.23](docker_remote_api_v1.23.md) documentation
 
 * `GET /containers/json` returns the state of the container, one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`.
+* `GET /containers/json` returns the mount points for the container.
 * `GET /networks/(name)` now returns an `Internal` field showing whether the network is internal or not.
 * `GET /networks/(name)` now returns an `EnableIPv6` field showing whether the network has ipv6 enabled or not.
 * `POST /containers/(name)/update` now supports updating container's restart policy.

+ 22 - 7
docs/reference/api/docker_remote_api_v1.23.md

@@ -73,7 +73,18 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:02"
                                   }
                          }
-                 }
+                 },
+                 "Mounts": [
+                         {
+                                  "Name": "fac362...80535",
+                                  "Source": "/data",
+                                  "Destination": "/data",
+                                  "Driver": "local",
+                                  "Mode": "ro,Z",
+                                  "RW": false,
+                                  "Propagation": ""
+                         }
+                 ]
          },
          {
                  "Id": "9cd87474be90",
@@ -102,8 +113,8 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:08"
                                   }
                          }
-                 }
-
+                 },
+                 "Mounts": []
          },
          {
                  "Id": "3176a2479c92",
@@ -132,8 +143,8 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:06"
                                   }
                          }
-                 }
-
+                 },
+                 "Mounts": []
          },
          {
                  "Id": "4cb07b47f9fb",
@@ -162,8 +173,8 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:05"
                                   }
                          }
-                 }
-
+                 },
+                 "Mounts": []
          }
     ]
 
@@ -184,6 +195,10 @@ Query Parameters:
   -   `status=`(`created`|`restarting`|`running`|`paused`|`exited`|`dead`)
   -   `label=key` or `label="key=value"` of a container label
   -   `isolation=`(`default`|`process`|`hyperv`)   (Windows daemon only)
+  -   `ancestor`=(`<image-name>[:<tag>]`,  `<image id>` or `<image@digest>`)
+  -   `before`=(`<container id>` or `<container name>`)
+  -   `since`=(`<container id>` or `<container name>`)
+  -   `volume`=(`<volume name>` or `<mount point destination>`)
 
 Status Codes:
 

+ 14 - 0
docs/reference/commandline/ps.md

@@ -60,6 +60,7 @@ The currently supported filters are:
 * before (container's id or name) - filters containers created before given id or name
 * since (container's id or name) - filters containers created since given id or name
 * isolation (default|process|hyperv)   (Windows daemon only)
+* volume (volume name or mount point) - filters containers that mount volumes.
 
 
 #### Label
@@ -193,6 +194,18 @@ with the same containers as in `before` filter:
     9c3527ed70ce        busybox     "top"         10 minutes ago      Up 10 minutes                           desperate_dubinsky
     4aace5031105        busybox     "top"         10 minutes ago      Up 10 minutes                           focused_hamilton
 
+#### Volume
+
+The `volume` filter shows only containers that mount a specific volume or have a volume mounted in a specific path:
+
+    $ docker ps --filter volume=remote-volume --format "table {{.ID}}\t{{.Mounts}}"
+    CONTAINER ID        MOUNTS
+    9c3527ed70ce        remote-volume
+
+    $ docker ps --filter volume=/data --format "table {{.ID}}\t{{.Mounts}}"
+    CONTAINER ID        MOUNTS
+    9c3527ed70ce        remote-volume
+
 
 ## Formatting
 
@@ -213,6 +226,7 @@ Placeholder | Description
 `.Names` | Container names.
 `.Labels` | All labels assigned to the container.
 `.Label` | Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
+`.Mounts` | Names of the volumes mounted in this container.
 
 When using the `--format` option, the `ps` command will either output the data exactly as the template
 declares or, when using the `table` directive, will include column headers as well.

+ 53 - 0
integration-cli/docker_cli_ps_test.go

@@ -734,3 +734,56 @@ func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
 	fields = strings.Fields(lines[1])
 	c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
 }
+
+func (s *DockerSuite) TestPsShowMounts(c *check.C) {
+	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
+
+	mp := prefix + slash + "test"
+
+	dockerCmd(c, "volume", "create", "--name", "ps-volume-test")
+	runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp)
+	c.Assert(waitRun("volume-test-1"), checker.IsNil)
+	runSleepingContainer(c, "--name=volume-test-2", "--volume", mp)
+	c.Assert(waitRun("volume-test-2"), checker.IsNil)
+
+	out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
+
+	lines := strings.Split(strings.TrimSpace(string(out)), "\n")
+	c.Assert(lines, checker.HasLen, 2)
+
+	fields := strings.Fields(lines[0])
+	c.Assert(fields, checker.HasLen, 2)
+
+	annonymounsVolumeID := fields[1]
+
+	fields = strings.Fields(lines[1])
+	c.Assert(fields[1], checker.Equals, "ps-volume-test")
+
+	// filter by volume name
+	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
+
+	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
+	c.Assert(lines, checker.HasLen, 1)
+
+	fields = strings.Fields(lines[0])
+	c.Assert(fields[1], checker.Equals, "ps-volume-test")
+
+	// empty results filtering by unknown volume
+	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist")
+	c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
+
+	// filter by mount destination
+	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
+
+	lines = strings.Split(strings.TrimSpace(string(out)), "\n")
+	c.Assert(lines, checker.HasLen, 2)
+
+	fields = strings.Fields(lines[0])
+	c.Assert(fields[1], checker.Equals, annonymounsVolumeID)
+	fields = strings.Fields(lines[1])
+	c.Assert(fields[1], checker.Equals, "ps-volume-test")
+
+	// empty results filtering by unknown mount point
+	out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted")
+	c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
+}

+ 14 - 0
man/docker-ps.1.md

@@ -35,6 +35,7 @@ the running containers.
    - before=(<container-name>|<container-id>)
    - since=(<container-name>|<container-id>)
    - ancestor=(<image-name>[:tag]|<image-id>|<image@digest>) - containers created from an image or a descendant.
+   - volume=(<volume-name>|<mount-point-destination>)
 
 **--format**="*TEMPLATE*"
    Pretty-print containers using a Go template.
@@ -50,6 +51,7 @@ the running containers.
       .Names - Container names.
       .Labels - All labels assigned to the container.
       .Label - Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
+      .Mounts - Names of the volumes mounted in this container.
 
 **--help**
   Print usage statement
@@ -118,6 +120,18 @@ the running containers.
     c1d3b0166030        debian
     41d50ecd2f57        fedora
 
+# Display containers with `remote-volume` mounted
+
+    $ docker ps --filter volume=remote-volume --format "table {{.ID}}\t{{.Mounts}}"
+    CONTAINER ID        MOUNTS
+    9c3527ed70ce        remote-volume
+
+# Display containers with a volume mounted in `/data`
+
+    $ docker ps --filter volume=/data --format "table {{.ID}}\t{{.Mounts}}"
+    CONTAINER ID        MOUNTS
+    9c3527ed70ce        remote-volume
+
 # HISTORY
 April 2014, Originally compiled by William Henry (whenry at redhat dot com)
 based on docker.com source material and internal work.