Explorar o código

Merge pull request #20017 from calavera/expose_volumes_in_ps

Add mounts to docker ps.
Sebastiaan van Stijn %!s(int64=9) %!d(string=hai) anos
pai
achega
034a1a8dfd

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

@@ -31,6 +31,7 @@ const (
 	repositoryHeader   = "REPOSITORY"
 	repositoryHeader   = "REPOSITORY"
 	tagHeader          = "TAG"
 	tagHeader          = "TAG"
 	digestHeader       = "DIGEST"
 	digestHeader       = "DIGEST"
+	mountsHeader       = "MOUNTS"
 )
 )
 
 
 type containerContext struct {
 type containerContext struct {
@@ -142,6 +143,20 @@ func (c *containerContext) Label(name string) string {
 	return c.c.Labels[name]
 	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 {
 type imageContext struct {
 	baseSubContext
 	baseSubContext
 	trunc  bool
 	trunc  bool

+ 23 - 0
daemon/list.go

@@ -9,6 +9,7 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/image"
+	"github.com/docker/docker/volume"
 	"github.com/docker/engine-api/types"
 	"github.com/docker/engine-api/types"
 	"github.com/docker/engine-api/types/filters"
 	"github.com/docker/engine-api/types/filters"
 	networktypes "github.com/docker/engine-api/types/network"
 	networktypes "github.com/docker/engine-api/types/network"
@@ -306,6 +307,27 @@ func includeContainerInList(container *container.Container, ctx *listContext) it
 		return excludeContainer
 		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 ctx.ancestorFilter {
 		if len(ctx.images) == 0 {
 		if len(ctx.images) == 0 {
 			return excludeContainer
 			return excludeContainer
@@ -419,6 +441,7 @@ func (daemon *Daemon) transformContainer(container *container.Container, ctx *li
 		newC.SizeRootFs = sizeRootFs
 		newC.SizeRootFs = sizeRootFs
 	}
 	}
 	newC.Labels = container.Config.Labels
 	newC.Labels = container.Config.Labels
+	newC.Mounts = addMountPoints(container)
 
 
 	return newC, nil
 	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
 [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 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 `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.
 * `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.
 * `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"
                                           "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",
                  "Id": "9cd87474be90",
@@ -102,8 +113,8 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:08"
                                           "MacAddress": "02:42:ac:11:00:08"
                                   }
                                   }
                          }
                          }
-                 }
-
+                 },
+                 "Mounts": []
          },
          },
          {
          {
                  "Id": "3176a2479c92",
                  "Id": "3176a2479c92",
@@ -132,8 +143,8 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:06"
                                           "MacAddress": "02:42:ac:11:00:06"
                                   }
                                   }
                          }
                          }
-                 }
-
+                 },
+                 "Mounts": []
          },
          },
          {
          {
                  "Id": "4cb07b47f9fb",
                  "Id": "4cb07b47f9fb",
@@ -162,8 +173,8 @@ List containers
                                           "MacAddress": "02:42:ac:11:00:05"
                                           "MacAddress": "02:42:ac:11:00:05"
                                   }
                                   }
                          }
                          }
-                 }
-
+                 },
+                 "Mounts": []
          }
          }
     ]
     ]
 
 
@@ -184,6 +195,10 @@ Query Parameters:
   -   `status=`(`created`|`restarting`|`running`|`paused`|`exited`|`dead`)
   -   `status=`(`created`|`restarting`|`running`|`paused`|`exited`|`dead`)
   -   `label=key` or `label="key=value"` of a container label
   -   `label=key` or `label="key=value"` of a container label
   -   `isolation=`(`default`|`process`|`hyperv`)   (Windows daemon only)
   -   `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:
 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
 * 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
 * since (container's id or name) - filters containers created since given id or name
 * isolation (default|process|hyperv)   (Windows daemon only)
 * isolation (default|process|hyperv)   (Windows daemon only)
+* volume (volume name or mount point) - filters containers that mount volumes.
 
 
 
 
 #### Label
 #### Label
@@ -193,6 +194,18 @@ with the same containers as in `before` filter:
     9c3527ed70ce        busybox     "top"         10 minutes ago      Up 10 minutes                           desperate_dubinsky
     9c3527ed70ce        busybox     "top"         10 minutes ago      Up 10 minutes                           desperate_dubinsky
     4aace5031105        busybox     "top"         10 minutes ago      Up 10 minutes                           focused_hamilton
     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
 ## Formatting
 
 
@@ -213,6 +226,7 @@ Placeholder | Description
 `.Names` | Container names.
 `.Names` | Container names.
 `.Labels` | All labels assigned to the container.
 `.Labels` | All labels assigned to the container.
 `.Label` | Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
 `.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
 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.
 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])
 	fields = strings.Fields(lines[1])
 	c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
 	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>)
    - before=(<container-name>|<container-id>)
    - since=(<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.
    - ancestor=(<image-name>[:tag]|<image-id>|<image@digest>) - containers created from an image or a descendant.
+   - volume=(<volume-name>|<mount-point-destination>)
 
 
 **--format**="*TEMPLATE*"
 **--format**="*TEMPLATE*"
    Pretty-print containers using a Go template.
    Pretty-print containers using a Go template.
@@ -50,6 +51,7 @@ the running containers.
       .Names - Container names.
       .Names - Container names.
       .Labels - All labels assigned to the container.
       .Labels - All labels assigned to the container.
       .Label - Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
       .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**
 **--help**
   Print usage statement
   Print usage statement
@@ -118,6 +120,18 @@ the running containers.
     c1d3b0166030        debian
     c1d3b0166030        debian
     41d50ecd2f57        fedora
     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
 # HISTORY
 April 2014, Originally compiled by William Henry (whenry at redhat dot com)
 April 2014, Originally compiled by William Henry (whenry at redhat dot com)
 based on docker.com source material and internal work.
 based on docker.com source material and internal work.