Skip to content

Commit d5ebad2

Browse files
committed
Add .IPAddresses as formatting option on docker ps
This allows showing the IP address for each network that the container is attached to, for example: docker network create foo docker run -d --name foo nginx:alpine docker network connect foo foo container container ls --format 'table {{.ID}}\\t{{join .IPAddresses ", "}}' CONTAINER ID IP ADDRESSES 17e7d1910fc0 bridge:172.17.0.2, foo:172.19.0.2 container container ls --format='{{json .IPAddresses}}' | jq . [ "bridge:172.17.0.2", "foo:172.19.0.2" ] Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent 8822cab commit d5ebad2

File tree

3 files changed

+88
-23
lines changed

3 files changed

+88
-23
lines changed

cli/command/formatter/container.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ import (
1616
const (
1717
defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}"
1818

19-
namesHeader = "NAMES"
20-
commandHeader = "COMMAND"
21-
runningForHeader = "CREATED"
22-
mountsHeader = "MOUNTS"
23-
localVolumes = "LOCAL VOLUMES"
24-
networksHeader = "NETWORKS"
19+
namesHeader = "NAMES"
20+
commandHeader = "COMMAND"
21+
runningForHeader = "CREATED"
22+
mountsHeader = "MOUNTS"
23+
localVolumes = "LOCAL VOLUMES"
24+
networksHeader = "NETWORKS"
25+
ipAddressesHeader = "IP ADDRESSES"
2526
)
2627

2728
// NewContainerFormat returns a Format for rendering using a Context
@@ -103,6 +104,7 @@ func NewContainerContext() *ContainerContext {
103104
"Mounts": mountsHeader,
104105
"LocalVolumes": localVolumes,
105106
"Networks": networksHeader,
107+
"IPAddresses": ipAddressesHeader,
106108
}
107109
return &containerCtx
108110
}
@@ -294,6 +296,25 @@ func (c *ContainerContext) Networks() string {
294296
return strings.Join(networks, ",")
295297
}
296298

299+
// IPAddresses returns the list of IP-addresses assigned to the container
300+
// IP-addresses are prefixed with the name of the network, separated with a colon.
301+
// For example: "bridge:192.168.1.10"
302+
func (c *ContainerContext) IPAddresses() []string {
303+
ipAddresses := []string{}
304+
if c.c.NetworkSettings == nil {
305+
return ipAddresses
306+
}
307+
for name, net := range c.c.NetworkSettings.Networks {
308+
if net.IPAddress != "" {
309+
ipAddresses = append(ipAddresses, name+":"+net.IPAddress)
310+
}
311+
if net.GlobalIPv6Address != "" {
312+
ipAddresses = append(ipAddresses, name+":"+net.GlobalIPv6Address)
313+
}
314+
}
315+
return ipAddresses
316+
}
317+
297318
// DisplayablePorts returns formatted string representing open ports of container
298319
// e.g. "0.0.0.0:80->9090/tcp, 9988/tcp"
299320
// it's used by command 'docker ps'

cli/command/formatter/container_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"testing"
99
"time"
1010

11+
"github.com/docker/docker/api/types/network"
12+
1113
"github.com/docker/cli/internal/test"
1214
"github.com/docker/docker/api/types"
1315
"github.com/docker/docker/pkg/stringid"
@@ -249,7 +251,7 @@ size: 0B
249251
}
250252

251253
containers := []types.Container{
252-
{ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime, State: "running"},
254+
{ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime, State: "running", NetworkSettings: &types.SummaryNetworkSettings{}},
253255
{ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime, State: "running"},
254256
}
255257

@@ -407,6 +409,36 @@ func TestContainerContextWriteJSONField(t *testing.T) {
407409
}
408410
}
409411

412+
func TestContainerContextIPAddresses(t *testing.T) {
413+
containers := []types.Container{
414+
{
415+
ID: "containerID1",
416+
NetworkSettings: &types.SummaryNetworkSettings{
417+
Networks: map[string]*network.EndpointSettings{
418+
"one": {IPAddress: "192.168.1.2"},
419+
"two": {IPAddress: "192.168.178.2"},
420+
},
421+
},
422+
},
423+
{
424+
ID: "containerID2",
425+
NetworkSettings: &types.SummaryNetworkSettings{
426+
Networks: map[string]*network.EndpointSettings{
427+
"one": {IPAddress: "192.168.1.3"},
428+
"two": {IPAddress: "192.168.178.3"},
429+
},
430+
},
431+
},
432+
}
433+
434+
out := bytes.NewBufferString("")
435+
err := ContainerWrite(Context{Format: "{{.IPAddresses}}", Output: out}, containers)
436+
assert.NilError(t, err)
437+
assert.Equal(t, out.String(), `[one:192.168.1.2 two:192.168.178.2]
438+
[one:192.168.1.3 two:192.168.178.3]
439+
`)
440+
}
441+
410442
func TestContainerBackCompat(t *testing.T) {
411443
containers := []types.Container{{ID: "brewhaha"}}
412444
cases := []string{

docs/reference/commandline/ps.md

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -399,22 +399,24 @@ template.
399399
400400
Valid placeholders for the Go template are listed below:
401401
402-
| Placeholder | Description |
403-
|:--------------|:------------------------------------------------------------------------------------------------|
404-
| `.ID` | Container ID |
405-
| `.Image` | Image ID |
406-
| `.Command` | Quoted command |
407-
| `.CreatedAt` | Time when the container was created. |
408-
| `.RunningFor` | Elapsed time since the container was started. |
409-
| `.Ports` | Exposed ports. |
410-
| `.State` | Container status (for example; "created", "running", "exited"). |
411-
| `.Status` | Container status with details about duration and health-status. |
412-
| `.Size` | Container disk size. |
413-
| `.Names` | Container names. |
414-
| `.Labels` | All labels assigned to the container. |
415-
| `.Label` | Value of a specific label for this container. For example `'{{.Label "com.docker.swarm.cpu"}}'` |
416-
| `.Mounts` | Names of the volumes mounted in this container. |
417-
| `.Networks` | Names of the networks attached to this container. |
402+
| Placeholder | Description |
403+
|:---------------|:------------------------------------------------------------------------------------------------|
404+
| `.ID` | Container ID |
405+
| `.Image` | Image ID |
406+
| `.Command` | Quoted command |
407+
| `.CreatedAt` | Time when the container was created. |
408+
| `.RunningFor` | Elapsed time since the container was started. |
409+
| `.Ports` | Exposed ports. |
410+
| `.State` | Container status (for example; "created", "running", "exited"). |
411+
| `.Status` | Container status with details about duration and health-status. |
412+
| `.Size` | Container disk size. |
413+
| `.Names` | Container names. |
414+
| `.Labels` | All labels assigned to the container. |
415+
| `.Label` | Value of a specific label for this container. For example `'{{.Label "com.docker.swarm.cpu"}}'` |
416+
| `.Mounts` | Names of the volumes mounted in this container. |
417+
| `.Networks` | Names of the networks attached to this container. |
418+
| `.IPAddresses` | List of IP-Addresses for each network that the container is attached to. |
419+
418420
419421
When using the `--format` option, the `ps` command will either output the data
420422
exactly as the template declares or, when using the `table` directive, includes
@@ -443,3 +445,13 @@ a87ecb4f327c com.docker.swarm.node=ubuntu,com.docker.swarm.storage=ssd
443445
c1d3b0166030 com.docker.swarm.node=debian,com.docker.swarm.cpu=6
444446
41d50ecd2f57 com.docker.swarm.node=fedora,com.docker.swarm.cpu=3,com.docker.swarm.storage=ssd
445447
```
448+
449+
Show the IP-addresses that containers have:
450+
451+
```bash
452+
$ docker ps --format "table {{.ID}}\\t{{join .IPAddresses \", \"}}"
453+
454+
CONTAINER ID IP ADDRESSES
455+
c0cf2877da71 bridge:172.17.0.3
456+
17e7d1910fc0 bridge:172.17.0.2, mynetwork:172.19.0.2
457+
```

0 commit comments

Comments
 (0)