diff --git a/components/engine/daemon/list.go b/components/engine/daemon/list.go index a0bf67b38b..fd5b78dd60 100644 --- a/components/engine/daemon/list.go +++ b/components/engine/daemon/list.go @@ -33,6 +33,7 @@ var acceptedPsFilterTags = map[string]bool{ "status": true, "since": true, "volume": true, + "network": true, } // iterationAction represents possible outcomes happening during the container iteration. @@ -374,6 +375,24 @@ func includeContainerInList(container *container.Container, ctx *listContext) it } } + networkExist := fmt.Errorf("container part of network") + if ctx.filters.Include("network") { + err := ctx.filters.WalkValues("network", func(value string) error { + if _, ok := container.NetworkSettings.Networks[value]; ok { + return networkExist + } + for _, nw := range container.NetworkSettings.Networks { + if nw.NetworkID == value { + return networkExist + } + } + return nil + }) + if err != networkExist { + return excludeContainer + } + } + return includeContainer } diff --git a/components/engine/docs/reference/api/docker_remote_api.md b/components/engine/docs/reference/api/docker_remote_api.md index c384f7e2e4..8b87496f2a 100644 --- a/components/engine/docs/reference/api/docker_remote_api.md +++ b/components/engine/docs/reference/api/docker_remote_api.md @@ -117,6 +117,7 @@ This section lists each version from latest to oldest. Each listing includes a * `POST /containers/create` now takes `StorageOpt` field. * `GET /info` now returns `SecurityOptions` field, showing if `apparmor`, `seccomp`, or `selinux` is supported. * `GET /networks` now supports filtering by `label` and `driver`. +* `GET /containers/json` now supports filtering containers by `network` name or id. * `POST /containers/create` now takes `MaximumIOps` and `MaximumIOBps` fields. Windows daemon only. * `POST /containers/create` now returns an HTTP 400 "bad parameter" message if no command is specified (instead of an HTTP 500 "server error") diff --git a/components/engine/docs/reference/api/docker_remote_api_v1.24.md b/components/engine/docs/reference/api/docker_remote_api_v1.24.md index 821340e05a..d525a71944 100644 --- a/components/engine/docs/reference/api/docker_remote_api_v1.24.md +++ b/components/engine/docs/reference/api/docker_remote_api_v1.24.md @@ -223,6 +223,7 @@ Query Parameters: - `before`=(`` or ``) - `since`=(`` or ``) - `volume`=(`` or ``) + - `network`=(`` or ``) Status Codes: diff --git a/components/engine/docs/reference/commandline/ps.md b/components/engine/docs/reference/commandline/ps.md index 1dda728a7f..c661c653dc 100644 --- a/components/engine/docs/reference/commandline/ps.md +++ b/components/engine/docs/reference/commandline/ps.md @@ -62,7 +62,7 @@ The currently supported filters are: * 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. - +* network (network id or name) - filters containers connected to the provided network #### Label @@ -207,6 +207,35 @@ The `volume` filter shows only containers that mount a specific volume or have a CONTAINER ID MOUNTS 9c3527ed70ce remote-volume +#### Network + +The `network` filter shows only containers that are connected to a network with +a given name or id. + +The following filter matches all containers that are connected to a network +with a name containing `net1`. + +```bash +$ docker run -d --net=net1 --name=test1 ubuntu top +$ docker run -d --net=net2 --name=test2 ubuntu top + +$ docker ps --filter network=net1 +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +9d4893ed80fe ubuntu "top" 10 minutes ago Up 10 minutes test1 +``` + +The network filter matches on both the network's name and id. The following +example shows all containers that are attached to the `net1` network, using +the network id as a filter; + +```bash +$ docker network inspect --format "{{.ID}}" net1 +8c0b4110ae930dbe26b258de9bc34a03f98056ed6f27f991d32919bfe401d7c5 + +$ docker ps --filter network=8c0b4110ae930dbe26b258de9bc34a03f98056ed6f27f991d32919bfe401d7c5 +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +9d4893ed80fe ubuntu "top" 10 minutes ago Up 10 minutes test1 +``` ## Formatting diff --git a/components/engine/integration-cli/docker_cli_ps_test.go b/components/engine/integration-cli/docker_cli_ps_test.go index 6e0ce2b392..a4ee9a9f65 100644 --- a/components/engine/integration-cli/docker_cli_ps_test.go +++ b/components/engine/integration-cli/docker_cli_ps_test.go @@ -804,3 +804,63 @@ func (s *DockerSuite) TestPsFormatSize(c *check.C) { lines = strings.Split(out, "\n") c.Assert(lines[8], checker.HasPrefix, "size:", check.Commentf("Size should be appended on a newline")) } + +func (s *DockerSuite) TestPsListContainersFilterNetwork(c *check.C) { + // TODO default network on Windows is not called "bridge", and creating a + // custom network fails on Windows fails with "Error response from daemon: plugin not found") + testRequires(c, DaemonIsLinux) + + // create some containers + runSleepingContainer(c, "--net=bridge", "--name=onbridgenetwork") + runSleepingContainer(c, "--net=none", "--name=onnonenetwork") + + // Filter docker ps on non existing network + out, _ := dockerCmd(c, "ps", "--filter", "network=doesnotexist") + containerOut := strings.TrimSpace(string(out)) + lines := strings.Split(containerOut, "\n") + + // skip header + lines = lines[1:] + + // ps output should have no containers + c.Assert(lines, checker.HasLen, 0) + + // Filter docker ps on network bridge + out, _ = dockerCmd(c, "ps", "--filter", "network=bridge") + containerOut = strings.TrimSpace(string(out)) + + lines = strings.Split(containerOut, "\n") + + // skip header + lines = lines[1:] + + // ps output should have only one container + c.Assert(lines, checker.HasLen, 1) + + // Making sure onbridgenetwork is on the output + c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on network\n")) + + // Filter docker ps on networks bridge and none + out, _ = dockerCmd(c, "ps", "--filter", "network=bridge", "--filter", "network=none") + containerOut = strings.TrimSpace(string(out)) + + lines = strings.Split(containerOut, "\n") + + // skip header + lines = lines[1:] + + //ps output should have both the containers + c.Assert(lines, checker.HasLen, 2) + + // Making sure onbridgenetwork and onnonenetwork is on the output + c.Assert(containerOut, checker.Contains, "onnonenetwork", check.Commentf("Missing the container on none network\n")) + c.Assert(containerOut, checker.Contains, "onbridgenetwork", check.Commentf("Missing the container on bridge network\n")) + + nwID, _ := dockerCmd(c, "network", "inspect", "--format", "{{.ID}}", "bridge") + + // Filter by network ID + out, _ = dockerCmd(c, "ps", "--filter", "network="+nwID) + containerOut = strings.TrimSpace(string(out)) + + c.Assert(containerOut, checker.Contains, "onbridgenetwork") +} diff --git a/components/engine/man/docker-ps.1.md b/components/engine/man/docker-ps.1.md index f567966487..14c770121f 100644 --- a/components/engine/man/docker-ps.1.md +++ b/components/engine/man/docker-ps.1.md @@ -36,6 +36,7 @@ the running containers. - since=(|) - ancestor=([:tag]||) - containers created from an image or a descendant. - volume=(|) + - network=(|) - containers connected to the provided network **--format**="*TEMPLATE*" Pretty-print containers using a Go template.