mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Add mounts to docker ps.
- Allow to filter containers by volume with `--filter volume=name` and `filter volume=/dest`. - Show their names in the list with the custom format `{{ .Mounts }}`. Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
64785ff146
commit
bd4fb00fb6
7 changed files with 142 additions and 7 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue