Skip to content

Commit 0cfea7d

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 <github@gone.nl>
1 parent 0b9d198 commit 0cfea7d

3 files changed

Lines changed: 88 additions & 24 deletions

File tree

cli/command/formatter/container.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ import (
2121
const (
2222
defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}"
2323

24-
namesHeader = "NAMES"
25-
commandHeader = "COMMAND"
26-
runningForHeader = "CREATED"
27-
mountsHeader = "MOUNTS"
28-
localVolumes = "LOCAL VOLUMES"
29-
networksHeader = "NETWORKS"
30-
platformHeader = "PLATFORM"
24+
namesHeader = "NAMES"
25+
commandHeader = "COMMAND"
26+
runningForHeader = "CREATED"
27+
mountsHeader = "MOUNTS"
28+
localVolumes = "LOCAL VOLUMES"
29+
networksHeader = "NETWORKS"
30+
platformHeader = "PLATFORM"
31+
ipAddressesHeader = "IP ADDRESSES"
3132
)
3233

3334
// Platform wraps a [ocispec.Platform] to implement the stringer interface.
@@ -121,6 +122,7 @@ func NewContainerContext() *ContainerContext {
121122
"LocalVolumes": localVolumes,
122123
"Networks": networksHeader,
123124
"Platform": platformHeader,
125+
"IPAddresses": ipAddressesHeader,
124126
}
125127
return &containerCtx
126128
}
@@ -341,6 +343,25 @@ func (c *ContainerContext) Networks() string {
341343
return strings.Join(networks, ",")
342344
}
343345

346+
// IPAddresses returns the list of IP-addresses assigned to the container
347+
// IP-addresses are prefixed with the name of the network, separated with a colon.
348+
// For example: "bridge:192.168.1.10"
349+
func (c *ContainerContext) IPAddresses() []string {
350+
ipAddresses := []string{}
351+
if c.c.NetworkSettings == nil {
352+
return ipAddresses
353+
}
354+
for name, nw := range c.c.NetworkSettings.Networks {
355+
if nw.IPAddress != "" {
356+
ipAddresses = append(ipAddresses, name+":"+nw.IPAddress)
357+
}
358+
if nw.GlobalIPv6Address != "" {
359+
ipAddresses = append(ipAddresses, name+":"+nw.GlobalIPv6Address)
360+
}
361+
}
362+
return ipAddresses
363+
}
364+
344365
// DisplayablePorts returns formatted string representing open ports of container
345366
// e.g. "0.0.0.0:80->9090/tcp, 9988/tcp"
346367
// it's used by command 'docker ps'

cli/command/formatter/container_test.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/docker/cli/internal/test"
1616
"github.com/moby/moby/api/types/container"
17+
"github.com/moby/moby/api/types/network"
1718
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1819
"gotest.tools/v3/assert"
1920
is "gotest.tools/v3/assert/cmp"
@@ -390,7 +391,7 @@ size: 0B
390391
}
391392

392393
containers := []container.Summary{
393-
{ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime, State: container.StateRunning},
394+
{ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime, State: container.StateRunning, NetworkSettings: &container.NetworkSettingsSummary{}},
394395
{ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime, State: container.StateRunning},
395396
}
396397

@@ -576,6 +577,36 @@ func TestContainerContextWriteJSONField(t *testing.T) {
576577
}
577578
}
578579

580+
func TestContainerContextIPAddresses(t *testing.T) {
581+
containers := []container.Summary{
582+
{
583+
ID: "containerID1",
584+
NetworkSettings: &container.NetworkSettingsSummary{
585+
Networks: map[string]*network.EndpointSettings{
586+
"one": {IPAddress: "192.168.1.2"},
587+
"two": {IPAddress: "192.168.178.2"},
588+
},
589+
},
590+
},
591+
{
592+
ID: "containerID2",
593+
NetworkSettings: &container.NetworkSettingsSummary{
594+
Networks: map[string]*network.EndpointSettings{
595+
"one": {IPAddress: "192.168.1.3"},
596+
"two": {IPAddress: "192.168.178.3"},
597+
},
598+
},
599+
},
600+
}
601+
602+
out := bytes.NewBufferString("")
603+
err := ContainerWrite(Context{Format: "{{.IPAddresses}}", Output: out}, containers)
604+
assert.NilError(t, err)
605+
assert.Equal(t, out.String(), `[one:192.168.1.2 two:192.168.178.2]
606+
[one:192.168.1.3 two:192.168.178.3]
607+
`)
608+
}
609+
579610
func TestContainerBackCompat(t *testing.T) {
580611
createdAtTime := time.Now().AddDate(-1, 0, 0) // 1 year ago
581612

docs/reference/commandline/container_ls.md

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -395,22 +395,24 @@ template.
395395

396396
Valid placeholders for the Go template are listed below:
397397

398-
| Placeholder | Description |
399-
|:--------------|:------------------------------------------------------------------------------------------------|
400-
| `.ID` | Container ID |
401-
| `.Image` | Image ID |
402-
| `.Command` | Quoted command |
403-
| `.CreatedAt` | Time when the container was created. |
404-
| `.RunningFor` | Elapsed time since the container was started. |
405-
| `.Ports` | Exposed ports. |
406-
| `.State` | Container status (for example; "created", "running", "exited"). |
407-
| `.Status` | Container status with details about duration and health-status. |
408-
| `.Size` | Container disk size. |
409-
| `.Names` | Container names. |
410-
| `.Labels` | All labels assigned to the container. |
411-
| `.Label` | Value of a specific label for this container. For example `'{{.Label "com.docker.swarm.cpu"}}'` |
412-
| `.Mounts` | Names of the volumes mounted in this container. |
413-
| `.Networks` | Names of the networks attached to this container. |
398+
| Placeholder | Description |
399+
|:---------------|:------------------------------------------------------------------------------------------------|
400+
| `.ID` | Container ID |
401+
| `.Image` | Image ID |
402+
| `.Command` | Quoted command |
403+
| `.CreatedAt` | Time when the container was created. |
404+
| `.RunningFor` | Elapsed time since the container was started. |
405+
| `.Ports` | Exposed ports. |
406+
| `.State` | Container status (for example; "created", "running", "exited"). |
407+
| `.Status` | Container status with details about duration and health-status. |
408+
| `.Size` | Container disk size. |
409+
| `.Names` | Container names. |
410+
| `.Labels` | All labels assigned to the container. |
411+
| `.Label` | Value of a specific label for this container. For example `'{{.Label "com.docker.swarm.cpu"}}'` |
412+
| `.Mounts` | Names of the volumes mounted in this container. |
413+
| `.Networks` | Names of the networks attached to this container. |
414+
| `.IPAddresses` | List of IP-Addresses for each network that the container is attached to. |
415+
414416

415417
When using the `--format` option, the `ps` command will either output the data
416418
exactly as the template declares or, when using the `table` directive, includes
@@ -446,3 +448,13 @@ To list all running containers in JSON format, use the `json` directive:
446448
$ docker ps --format json
447449
{"Command":"\"/docker-entrypoint.…\"","CreatedAt":"2021-03-10 00:15:05 +0100 CET","ID":"a762a2b37a1d","Image":"nginx","Labels":"maintainer=NGINX Docker Maintainers \u003cdocker-maint@nginx.com\u003e","LocalVolumes":"0","Mounts":"","Names":"boring_keldysh","Networks":"bridge","Ports":"80/tcp","RunningFor":"4 seconds ago","Size":"0B","State":"running","Status":"Up 3 seconds"}
448450
```
451+
452+
Show the IP-addresses that containers have:
453+
454+
```console
455+
$ docker ps --format "table {{.ID}}\\t{{join .IPAddresses \", \"}}"
456+
457+
CONTAINER ID IP ADDRESSES
458+
c0cf2877da71 bridge:172.17.0.3
459+
17e7d1910fc0 bridge:172.17.0.2, mynetwork:172.19.0.2
460+
```

0 commit comments

Comments
 (0)