Skip to content

Commit 034a1a8

Browse files
committed
Merge pull request moby#20017 from calavera/expose_volumes_in_ps
Add mounts to docker ps.
2 parents 2d0c3d1 + bd4fb00 commit 034a1a8

File tree

7 files changed

+142
-7
lines changed

7 files changed

+142
-7
lines changed

api/client/formatter/custom.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
repositoryHeader = "REPOSITORY"
3232
tagHeader = "TAG"
3333
digestHeader = "DIGEST"
34+
mountsHeader = "MOUNTS"
3435
)
3536

3637
type containerContext struct {
@@ -142,6 +143,20 @@ func (c *containerContext) Label(name string) string {
142143
return c.c.Labels[name]
143144
}
144145

146+
func (c *containerContext) Mounts() string {
147+
c.addHeader(mountsHeader)
148+
149+
var mounts []string
150+
for _, m := range c.c.Mounts {
151+
name := m.Name
152+
if c.trunc {
153+
name = stringutils.Truncate(name, 15)
154+
}
155+
mounts = append(mounts, name)
156+
}
157+
return strings.Join(mounts, ",")
158+
}
159+
145160
type imageContext struct {
146161
baseSubContext
147162
trunc bool

daemon/list.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/Sirupsen/logrus"
1010
"github.com/docker/docker/container"
1111
"github.com/docker/docker/image"
12+
"github.com/docker/docker/volume"
1213
"github.com/docker/engine-api/types"
1314
"github.com/docker/engine-api/types/filters"
1415
networktypes "github.com/docker/engine-api/types/network"
@@ -306,6 +307,27 @@ func includeContainerInList(container *container.Container, ctx *listContext) it
306307
return excludeContainer
307308
}
308309

310+
if ctx.filters.Include("volume") {
311+
volumesByName := make(map[string]*volume.MountPoint)
312+
for _, m := range container.MountPoints {
313+
volumesByName[m.Name] = m
314+
}
315+
316+
volumeExist := fmt.Errorf("volume mounted in container")
317+
err := ctx.filters.WalkValues("volume", func(value string) error {
318+
if _, exist := container.MountPoints[value]; exist {
319+
return volumeExist
320+
}
321+
if _, exist := volumesByName[value]; exist {
322+
return volumeExist
323+
}
324+
return nil
325+
})
326+
if err != volumeExist {
327+
return excludeContainer
328+
}
329+
}
330+
309331
if ctx.ancestorFilter {
310332
if len(ctx.images) == 0 {
311333
return excludeContainer
@@ -419,6 +441,7 @@ func (daemon *Daemon) transformContainer(container *container.Container, ctx *li
419441
newC.SizeRootFs = sizeRootFs
420442
}
421443
newC.Labels = container.Config.Labels
444+
newC.Mounts = addMountPoints(container)
422445

423446
return newC, nil
424447
}

docs/reference/api/docker_remote_api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ This section lists each version from latest to oldest. Each listing includes a
116116
[Docker Remote API v1.23](docker_remote_api_v1.23.md) documentation
117117

118118
* `GET /containers/json` returns the state of the container, one of `created`, `restarting`, `running`, `paused`, `exited` or `dead`.
119+
* `GET /containers/json` returns the mount points for the container.
119120
* `GET /networks/(name)` now returns an `Internal` field showing whether the network is internal or not.
120121
* `GET /networks/(name)` now returns an `EnableIPv6` field showing whether the network has ipv6 enabled or not.
121122
* `POST /containers/(name)/update` now supports updating container's restart policy.

docs/reference/api/docker_remote_api_v1.23.md

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,18 @@ List containers
7373
"MacAddress": "02:42:ac:11:00:02"
7474
}
7575
}
76-
}
76+
},
77+
"Mounts": [
78+
{
79+
"Name": "fac362...80535",
80+
"Source": "/data",
81+
"Destination": "/data",
82+
"Driver": "local",
83+
"Mode": "ro,Z",
84+
"RW": false,
85+
"Propagation": ""
86+
}
87+
]
7788
},
7889
{
7990
"Id": "9cd87474be90",
@@ -102,8 +113,8 @@ List containers
102113
"MacAddress": "02:42:ac:11:00:08"
103114
}
104115
}
105-
}
106-
116+
},
117+
"Mounts": []
107118
},
108119
{
109120
"Id": "3176a2479c92",
@@ -132,8 +143,8 @@ List containers
132143
"MacAddress": "02:42:ac:11:00:06"
133144
}
134145
}
135-
}
136-
146+
},
147+
"Mounts": []
137148
},
138149
{
139150
"Id": "4cb07b47f9fb",
@@ -162,8 +173,8 @@ List containers
162173
"MacAddress": "02:42:ac:11:00:05"
163174
}
164175
}
165-
}
166-
176+
},
177+
"Mounts": []
167178
}
168179
]
169180

@@ -184,6 +195,10 @@ Query Parameters:
184195
- `status=`(`created`|`restarting`|`running`|`paused`|`exited`|`dead`)
185196
- `label=key` or `label="key=value"` of a container label
186197
- `isolation=`(`default`|`process`|`hyperv`) (Windows daemon only)
198+
- `ancestor`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`)
199+
- `before`=(`<container id>` or `<container name>`)
200+
- `since`=(`<container id>` or `<container name>`)
201+
- `volume`=(`<volume name>` or `<mount point destination>`)
187202

188203
Status Codes:
189204

docs/reference/commandline/ps.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ The currently supported filters are:
6060
* before (container's id or name) - filters containers created before given id or name
6161
* since (container's id or name) - filters containers created since given id or name
6262
* isolation (default|process|hyperv) (Windows daemon only)
63+
* volume (volume name or mount point) - filters containers that mount volumes.
6364

6465

6566
#### Label
@@ -193,6 +194,18 @@ with the same containers as in `before` filter:
193194
9c3527ed70ce busybox "top" 10 minutes ago Up 10 minutes desperate_dubinsky
194195
4aace5031105 busybox "top" 10 minutes ago Up 10 minutes focused_hamilton
195196

197+
#### Volume
198+
199+
The `volume` filter shows only containers that mount a specific volume or have a volume mounted in a specific path:
200+
201+
$ docker ps --filter volume=remote-volume --format "table {{.ID}}\t{{.Mounts}}"
202+
CONTAINER ID MOUNTS
203+
9c3527ed70ce remote-volume
204+
205+
$ docker ps --filter volume=/data --format "table {{.ID}}\t{{.Mounts}}"
206+
CONTAINER ID MOUNTS
207+
9c3527ed70ce remote-volume
208+
196209

197210
## Formatting
198211

@@ -213,6 +226,7 @@ Placeholder | Description
213226
`.Names` | Container names.
214227
`.Labels` | All labels assigned to the container.
215228
`.Label` | Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
229+
`.Mounts` | Names of the volumes mounted in this container.
216230

217231
When using the `--format` option, the `ps` command will either output the data exactly as the template
218232
declares or, when using the `table` directive, will include column headers as well.

integration-cli/docker_cli_ps_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,56 @@ func (s *DockerSuite) TestPsNotShowPortsOfStoppedContainer(c *check.C) {
734734
fields = strings.Fields(lines[1])
735735
c.Assert(fields[len(fields)-2], checker.Not(checker.Equals), expected, check.Commentf("Should not got %v", expected))
736736
}
737+
738+
func (s *DockerSuite) TestPsShowMounts(c *check.C) {
739+
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
740+
741+
mp := prefix + slash + "test"
742+
743+
dockerCmd(c, "volume", "create", "--name", "ps-volume-test")
744+
runSleepingContainer(c, "--name=volume-test-1", "--volume", "ps-volume-test:"+mp)
745+
c.Assert(waitRun("volume-test-1"), checker.IsNil)
746+
runSleepingContainer(c, "--name=volume-test-2", "--volume", mp)
747+
c.Assert(waitRun("volume-test-2"), checker.IsNil)
748+
749+
out, _ := dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}")
750+
751+
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
752+
c.Assert(lines, checker.HasLen, 2)
753+
754+
fields := strings.Fields(lines[0])
755+
c.Assert(fields, checker.HasLen, 2)
756+
757+
annonymounsVolumeID := fields[1]
758+
759+
fields = strings.Fields(lines[1])
760+
c.Assert(fields[1], checker.Equals, "ps-volume-test")
761+
762+
// filter by volume name
763+
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=ps-volume-test")
764+
765+
lines = strings.Split(strings.TrimSpace(string(out)), "\n")
766+
c.Assert(lines, checker.HasLen, 1)
767+
768+
fields = strings.Fields(lines[0])
769+
c.Assert(fields[1], checker.Equals, "ps-volume-test")
770+
771+
// empty results filtering by unknown volume
772+
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume=this-volume-should-not-exist")
773+
c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
774+
775+
// filter by mount destination
776+
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+mp)
777+
778+
lines = strings.Split(strings.TrimSpace(string(out)), "\n")
779+
c.Assert(lines, checker.HasLen, 2)
780+
781+
fields = strings.Fields(lines[0])
782+
c.Assert(fields[1], checker.Equals, annonymounsVolumeID)
783+
fields = strings.Fields(lines[1])
784+
c.Assert(fields[1], checker.Equals, "ps-volume-test")
785+
786+
// empty results filtering by unknown mount point
787+
out, _ = dockerCmd(c, "ps", "--format", "{{.Names}} {{.Mounts}}", "--filter", "volume="+prefix+slash+"this-path-was-never-mounted")
788+
c.Assert(strings.TrimSpace(string(out)), checker.HasLen, 0)
789+
}

man/docker-ps.1.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ the running containers.
3535
- before=(<container-name>|<container-id>)
3636
- since=(<container-name>|<container-id>)
3737
- ancestor=(<image-name>[:tag]|<image-id>|<image@digest>) - containers created from an image or a descendant.
38+
- volume=(<volume-name>|<mount-point-destination>)
3839

3940
**--format**="*TEMPLATE*"
4041
Pretty-print containers using a Go template.
@@ -50,6 +51,7 @@ the running containers.
5051
.Names - Container names.
5152
.Labels - All labels assigned to the container.
5253
.Label - Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
54+
.Mounts - Names of the volumes mounted in this container.
5355

5456
**--help**
5557
Print usage statement
@@ -118,6 +120,18 @@ the running containers.
118120
c1d3b0166030 debian
119121
41d50ecd2f57 fedora
120122

123+
# Display containers with `remote-volume` mounted
124+
125+
$ docker ps --filter volume=remote-volume --format "table {{.ID}}\t{{.Mounts}}"
126+
CONTAINER ID MOUNTS
127+
9c3527ed70ce remote-volume
128+
129+
# Display containers with a volume mounted in `/data`
130+
131+
$ docker ps --filter volume=/data --format "table {{.ID}}\t{{.Mounts}}"
132+
CONTAINER ID MOUNTS
133+
9c3527ed70ce remote-volume
134+
121135
# HISTORY
122136
April 2014, Originally compiled by William Henry (whenry at redhat dot com)
123137
based on docker.com source material and internal work.

0 commit comments

Comments
 (0)