mirror of https://github.com/docker/docs.git
Docker ps custom formatting.
Docker-DCO-1.1-Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
de0e883331
commit
37209190c7
|
@ -179,6 +179,10 @@ func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (cli *DockerCli) PsFormat() string {
|
||||
return cli.configFile.PsFormat
|
||||
}
|
||||
|
||||
// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err.
|
||||
// The key file, protocol (i.e. unix) and address are passed in as strings, along with the tls.Config. If the tls.Config
|
||||
// is set the client scheme will be set to https.
|
||||
|
|
149
api/client/ps.go
149
api/client/ps.go
|
@ -2,21 +2,14 @@ package client
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/client/ps"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/opts"
|
||||
flag "github.com/docker/docker/pkg/mflag"
|
||||
"github.com/docker/docker/pkg/parsers/filters"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/docker/docker/pkg/units"
|
||||
)
|
||||
|
||||
// CmdPs outputs a list of Docker containers.
|
||||
|
@ -38,7 +31,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
|||
since = cmd.String([]string{"#sinceId", "#-since-id", "-since"}, "", "Show created since Id or Name, include non-running")
|
||||
before = cmd.String([]string{"#beforeId", "#-before-id", "-before"}, "", "Show only container created before Id or Name")
|
||||
last = cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running")
|
||||
fields = cmd.String([]string{"-fields"}, "cimtspn", "Choose fields to print, and order (c,i,m,t,s,p,n,z)")
|
||||
format = cmd.String([]string{"F", "-format"}, "", "Pretty-print containers using a Go template")
|
||||
flFilter = opts.NewListOpts(nil)
|
||||
)
|
||||
cmd.Require(flag.Exact, 0)
|
||||
|
@ -99,136 +92,24 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
|
||||
if *quiet {
|
||||
*fields = "c"
|
||||
}
|
||||
|
||||
if *size {
|
||||
*fields = *fields + "z"
|
||||
}
|
||||
|
||||
if !*quiet {
|
||||
headermap := map[rune]string{
|
||||
'c': "CONTAINER ID",
|
||||
'i': "IMAGE",
|
||||
'm': "COMMAND",
|
||||
's': "STATUS",
|
||||
't': "CREATED",
|
||||
'p': "PORTS",
|
||||
'n': "NAMES",
|
||||
'z': "SIZE",
|
||||
}
|
||||
|
||||
headers := make([]string, 0)
|
||||
for _, v := range *fields {
|
||||
if title, ok := headermap[v]; ok {
|
||||
headers = append(headers, title)
|
||||
}
|
||||
}
|
||||
|
||||
if len(headers) > 0 {
|
||||
fmt.Fprint(w, strings.Join(headers, "\t")+"\n")
|
||||
f := *format
|
||||
if len(f) == 0 {
|
||||
if len(cli.PsFormat()) > 0 {
|
||||
f = cli.PsFormat()
|
||||
} else {
|
||||
f = "table"
|
||||
}
|
||||
}
|
||||
|
||||
stripNamePrefix := func(ss []string) []string {
|
||||
for i, s := range ss {
|
||||
ss[i] = s[1:]
|
||||
}
|
||||
|
||||
return ss
|
||||
psCtx := ps.Context{
|
||||
Output: cli.out,
|
||||
Format: f,
|
||||
Quiet: *quiet,
|
||||
Size: *size,
|
||||
Trunc: !*noTrunc,
|
||||
}
|
||||
|
||||
type containerMeta struct {
|
||||
c string
|
||||
i string
|
||||
m string
|
||||
t string
|
||||
s string
|
||||
p string
|
||||
n string
|
||||
z string
|
||||
}
|
||||
|
||||
var displayPort string
|
||||
if container.HostConfig.NetworkMode == "host" {
|
||||
displayPort = "*/tcp, */udp"
|
||||
} else {
|
||||
displayPort = api.DisplayablePorts(container.Ports)
|
||||
}
|
||||
|
||||
outp := make([]containerMeta, 0)
|
||||
for _, container := range containers {
|
||||
next := containerMeta{
|
||||
c: container.ID,
|
||||
n: "",
|
||||
m: strconv.Quote(container.Command),
|
||||
i: container.Image,
|
||||
t: units.HumanDuration(time.Now().UTC().Sub(time.Unix(int64(container.Created), 0))) + " ago",
|
||||
s: container.Status,
|
||||
p: displayPort,
|
||||
z: fmt.Sprintf("%s", units.HumanSize(float64(container.SizeRw))),
|
||||
}
|
||||
|
||||
// handle truncation
|
||||
outNames := stripNamePrefix(container.Names)
|
||||
if !*noTrunc {
|
||||
next.c = stringid.TruncateID(next.c)
|
||||
next.m = stringutils.Truncate(next.m, 20)
|
||||
// only display the default name for the container with notrunc is passed
|
||||
for _, name := range outNames {
|
||||
if len(strings.Split(name, "/")) == 1 {
|
||||
outNames = []string{name}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
next.n = strings.Join(outNames, ",")
|
||||
|
||||
if next.i == "" {
|
||||
next.i = "<no image>"
|
||||
}
|
||||
|
||||
// handle rootfs sizing
|
||||
if container.SizeRootFs > 0 {
|
||||
next.z = next.z + fmt.Sprintf(" (virtual %s)", units.HumanSize(float64(container.SizeRootFs)))
|
||||
}
|
||||
|
||||
outp = append(outp, next)
|
||||
}
|
||||
|
||||
for _, out := range outp {
|
||||
of := make([]string, 0)
|
||||
for _, v := range *fields {
|
||||
switch v {
|
||||
case 'c':
|
||||
of = append(of, out.c)
|
||||
case 'i':
|
||||
of = append(of, out.i)
|
||||
case 'm':
|
||||
of = append(of, out.m)
|
||||
case 't':
|
||||
of = append(of, out.t)
|
||||
case 's':
|
||||
of = append(of, out.s)
|
||||
case 'p':
|
||||
of = append(of, out.p)
|
||||
case 'n':
|
||||
of = append(of, out.n)
|
||||
case 'z':
|
||||
of = append(of, out.z)
|
||||
|
||||
}
|
||||
}
|
||||
if len(of) > 0 {
|
||||
fmt.Fprintf(w, "%s\n", strings.Join(of, "\t"))
|
||||
}
|
||||
}
|
||||
|
||||
if !*quiet {
|
||||
w.Flush()
|
||||
}
|
||||
ps.Format(psCtx, containers)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
package ps
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/docker/docker/pkg/units"
|
||||
)
|
||||
|
||||
const (
|
||||
tableKey = "table"
|
||||
|
||||
idHeader = "CONTAINER ID"
|
||||
imageHeader = "IMAGE"
|
||||
namesHeader = "NAMES"
|
||||
commandHeader = "COMMAND"
|
||||
createdAtHeader = "CREATED AT"
|
||||
runningForHeader = "CREATED"
|
||||
statusHeader = "STATUS"
|
||||
portsHeader = "PORTS"
|
||||
sizeHeader = "SIZE"
|
||||
labelsHeader = "LABELS"
|
||||
)
|
||||
|
||||
type containerContext struct {
|
||||
trunc bool
|
||||
header []string
|
||||
c types.Container
|
||||
}
|
||||
|
||||
func (c *containerContext) ID() string {
|
||||
c.addHeader(idHeader)
|
||||
if c.trunc {
|
||||
return stringid.TruncateID(c.c.ID)
|
||||
}
|
||||
return c.c.ID
|
||||
}
|
||||
|
||||
func (c *containerContext) Names() string {
|
||||
c.addHeader(namesHeader)
|
||||
names := stripNamePrefix(c.c.Names)
|
||||
if c.trunc {
|
||||
for _, name := range names {
|
||||
if len(strings.Split(name, "/")) == 1 {
|
||||
names = []string{name}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return strings.Join(names, ",")
|
||||
}
|
||||
|
||||
func (c *containerContext) Image() string {
|
||||
c.addHeader(imageHeader)
|
||||
if c.c.Image == "" {
|
||||
return "<no image>"
|
||||
}
|
||||
return c.c.Image
|
||||
}
|
||||
|
||||
func (c *containerContext) Command() string {
|
||||
c.addHeader(commandHeader)
|
||||
command := c.c.Command
|
||||
if c.trunc {
|
||||
command = stringutils.Truncate(command, 20)
|
||||
}
|
||||
return strconv.Quote(command)
|
||||
}
|
||||
|
||||
func (c *containerContext) CreatedAt() string {
|
||||
c.addHeader(createdAtHeader)
|
||||
return time.Unix(int64(c.c.Created), 0).String()
|
||||
}
|
||||
|
||||
func (c *containerContext) RunningFor() string {
|
||||
c.addHeader(runningForHeader)
|
||||
createdAt := time.Unix(int64(c.c.Created), 0)
|
||||
return units.HumanDuration(time.Now().UTC().Sub(createdAt))
|
||||
}
|
||||
|
||||
func (c *containerContext) Ports() string {
|
||||
c.addHeader(portsHeader)
|
||||
return api.DisplayablePorts(c.c.Ports)
|
||||
}
|
||||
|
||||
func (c *containerContext) Status() string {
|
||||
c.addHeader(statusHeader)
|
||||
return c.c.Status
|
||||
}
|
||||
|
||||
func (c *containerContext) Size() string {
|
||||
c.addHeader(sizeHeader)
|
||||
srw := units.HumanSize(float64(c.c.SizeRw))
|
||||
sv := units.HumanSize(float64(c.c.SizeRootFs))
|
||||
|
||||
sf := srw
|
||||
if c.c.SizeRootFs > 0 {
|
||||
sf = fmt.Sprintf("%s (virtual %s)", srw, sv)
|
||||
}
|
||||
return sf
|
||||
}
|
||||
|
||||
func (c *containerContext) Labels() string {
|
||||
c.addHeader(labelsHeader)
|
||||
if c.c.Labels == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
var joinLabels []string
|
||||
for k, v := range c.c.Labels {
|
||||
joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
return strings.Join(joinLabels, ",")
|
||||
}
|
||||
|
||||
func (c *containerContext) Label(name string) string {
|
||||
n := strings.Split(name, ".")
|
||||
r := strings.NewReplacer("-", " ", "_", " ")
|
||||
h := r.Replace(n[len(n)-1])
|
||||
|
||||
c.addHeader(h)
|
||||
|
||||
if c.c.Labels == nil {
|
||||
return ""
|
||||
}
|
||||
return c.c.Labels[name]
|
||||
}
|
||||
|
||||
func (c *containerContext) fullHeader() string {
|
||||
if c.header == nil {
|
||||
return ""
|
||||
}
|
||||
return strings.Join(c.header, "\t")
|
||||
}
|
||||
|
||||
func (c *containerContext) addHeader(header string) {
|
||||
if c.header == nil {
|
||||
c.header = []string{}
|
||||
}
|
||||
c.header = append(c.header, strings.ToUpper(header))
|
||||
}
|
||||
|
||||
func customFormat(ctx Context, containers []types.Container) {
|
||||
var (
|
||||
table bool
|
||||
header string
|
||||
format = ctx.Format
|
||||
buffer = bytes.NewBufferString("")
|
||||
)
|
||||
|
||||
if strings.HasPrefix(ctx.Format, tableKey) {
|
||||
table = true
|
||||
format = format[len(tableKey):]
|
||||
}
|
||||
|
||||
format = strings.Trim(format, " ")
|
||||
r := strings.NewReplacer(`\t`, "\t", `\n`, "\n")
|
||||
format = r.Replace(format)
|
||||
|
||||
if table && ctx.Size {
|
||||
format += "\t{{.Size}}"
|
||||
}
|
||||
|
||||
tmpl, err := template.New("ps template").Parse(format)
|
||||
if err != nil {
|
||||
buffer.WriteString(fmt.Sprintf("Invalid `docker ps` format: %v\n", err))
|
||||
}
|
||||
|
||||
for _, container := range containers {
|
||||
containerCtx := &containerContext{
|
||||
trunc: ctx.Trunc,
|
||||
c: container,
|
||||
}
|
||||
if err := tmpl.Execute(buffer, containerCtx); err != nil {
|
||||
buffer = bytes.NewBufferString(fmt.Sprintf("Invalid `docker ps` format: %v\n", err))
|
||||
break
|
||||
}
|
||||
if table && len(header) == 0 {
|
||||
header = containerCtx.fullHeader()
|
||||
}
|
||||
buffer.WriteString("\n")
|
||||
}
|
||||
|
||||
if table {
|
||||
t := tabwriter.NewWriter(ctx.Output, 20, 1, 3, ' ', 0)
|
||||
t.Write([]byte(header))
|
||||
t.Write([]byte("\n"))
|
||||
buffer.WriteTo(t)
|
||||
t.Flush()
|
||||
} else {
|
||||
buffer.WriteTo(ctx.Output)
|
||||
}
|
||||
}
|
||||
|
||||
func stripNamePrefix(ss []string) []string {
|
||||
for i, s := range ss {
|
||||
ss[i] = s[1:]
|
||||
}
|
||||
|
||||
return ss
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package ps
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
)
|
||||
|
||||
func TestContainerContextID(t *testing.T) {
|
||||
containerId := stringid.GenerateRandomID()
|
||||
unix := time.Now().Unix()
|
||||
|
||||
var ctx containerContext
|
||||
cases := []struct {
|
||||
container types.Container
|
||||
trunc bool
|
||||
expValue string
|
||||
expHeader string
|
||||
call func() string
|
||||
}{
|
||||
{types.Container{ID: containerId}, true, stringid.TruncateID(containerId), idHeader, ctx.ID},
|
||||
{types.Container{Names: []string{"/foobar_baz"}}, true, "foobar_baz", namesHeader, ctx.Names},
|
||||
{types.Container{Image: "ubuntu"}, true, "ubuntu", imageHeader, ctx.Image},
|
||||
{types.Container{Image: ""}, true, "<no image>", imageHeader, ctx.Image},
|
||||
{types.Container{Command: "sh -c 'ls -la'"}, true, `"sh -c 'ls -la'"`, commandHeader, ctx.Command},
|
||||
{types.Container{Created: int(unix)}, true, time.Unix(unix, 0).String(), createdAtHeader, ctx.CreatedAt},
|
||||
{types.Container{Ports: []types.Port{types.Port{PrivatePort: 8080, PublicPort: 8080, Type: "tcp"}}}, true, "8080/tcp", portsHeader, ctx.Ports},
|
||||
{types.Container{Status: "RUNNING"}, true, "RUNNING", statusHeader, ctx.Status},
|
||||
{types.Container{SizeRw: 10}, true, "10 B", sizeHeader, ctx.Size},
|
||||
{types.Container{SizeRw: 10, SizeRootFs: 20}, true, "10 B (virtual 20 B)", sizeHeader, ctx.Size},
|
||||
{types.Container{Labels: map[string]string{"cpu": "6", "storage": "ssd"}}, true, "cpu=6,storage=ssd", labelsHeader, ctx.Labels},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
ctx = containerContext{c: c.container, trunc: c.trunc}
|
||||
v := c.call()
|
||||
if v != c.expValue {
|
||||
t.Fatalf("Expected %s, was %s\n", c.expValue, v)
|
||||
}
|
||||
|
||||
h := ctx.fullHeader()
|
||||
if h != c.expHeader {
|
||||
t.Fatalf("Expected %s, was %s\n", c.expHeader, h)
|
||||
}
|
||||
}
|
||||
|
||||
c := types.Container{Labels: map[string]string{"com.docker.swarm.swarm-id": "33", "com.docker.swarm.node_name": "ubuntu"}}
|
||||
ctx = containerContext{c: c, trunc: true}
|
||||
|
||||
sid := ctx.Label("com.docker.swarm.swarm-id")
|
||||
node := ctx.Label("com.docker.swarm.node_name")
|
||||
if sid != "33" {
|
||||
t.Fatal("Expected 33, was %s\n", sid)
|
||||
}
|
||||
|
||||
if node != "ubuntu" {
|
||||
t.Fatal("Expected ubuntu, was %s\n", node)
|
||||
}
|
||||
|
||||
h := ctx.fullHeader()
|
||||
if h != "SWARM ID\tNODE NAME" {
|
||||
t.Fatal("Expected %s, was %s\n", "SWARM ID\tNODE NAME", h)
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package ps
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
|
||||
const (
|
||||
tableFormatKey = "table"
|
||||
rawFormatKey = "raw"
|
||||
|
||||
defaultTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}} ago\t{{.Status}}\t{{.Ports}}\t{{.Names}}"
|
||||
defaultQuietFormat = "{{.ID}}"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
Output io.Writer
|
||||
Format string
|
||||
Size bool
|
||||
Quiet bool
|
||||
Trunc bool
|
||||
}
|
||||
|
||||
func Format(ctx Context, containers []types.Container) {
|
||||
switch ctx.Format {
|
||||
case tableFormatKey:
|
||||
tableFormat(ctx, containers)
|
||||
case rawFormatKey:
|
||||
rawFormat(ctx, containers)
|
||||
default:
|
||||
customFormat(ctx, containers)
|
||||
}
|
||||
}
|
||||
|
||||
func rawFormat(ctx Context, containers []types.Container) {
|
||||
if ctx.Quiet {
|
||||
ctx.Format = `container_id: {{.ID}}`
|
||||
} else {
|
||||
ctx.Format = `container_id: {{.ID}}
|
||||
image: {{.Image}}
|
||||
command: {{.Command}}
|
||||
created_at: {{.CreatedAt}}
|
||||
status: {{.Status}}
|
||||
names: {{.Names}}
|
||||
labels: {{.Labels}}
|
||||
ports: {{.Ports}}
|
||||
`
|
||||
if ctx.Size {
|
||||
ctx.Format += `size: {{.Size}}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customFormat(ctx, containers)
|
||||
}
|
||||
|
||||
func tableFormat(ctx Context, containers []types.Container) {
|
||||
ctx.Format = defaultTableFormat
|
||||
if ctx.Quiet {
|
||||
ctx.Format = defaultQuietFormat
|
||||
}
|
||||
|
||||
customFormat(ctx, containers)
|
||||
}
|
|
@ -57,6 +57,7 @@ type AuthConfig struct {
|
|||
type ConfigFile struct {
|
||||
AuthConfigs map[string]AuthConfig `json:"auths"`
|
||||
HTTPHeaders map[string]string `json:"HttpHeaders,omitempty"`
|
||||
PsFormat string `json:"psFormat,omitempty"`
|
||||
filename string // Note: not serialized - for internal use only
|
||||
}
|
||||
|
||||
|
|
|
@ -155,3 +155,34 @@ func TestNewJson(t *testing.T) {
|
|||
t.Fatalf("Should have save in new form: %s", string(buf))
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonWithPsFormat(t *testing.T) {
|
||||
tmpHome, _ := ioutil.TempDir("", "config-test")
|
||||
fn := filepath.Join(tmpHome, CONFIGFILE)
|
||||
js := `{
|
||||
"auths": { "https://index.docker.io/v1/": { "auth": "am9lam9lOmhlbGxv", "email": "user@example.com" } },
|
||||
"psFormat": "table {{.ID}}\\t{{.Label \"com.docker.label.cpu\"}}"
|
||||
}`
|
||||
ioutil.WriteFile(fn, []byte(js), 0600)
|
||||
|
||||
config, err := Load(tmpHome)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed loading on empty json file: %q", err)
|
||||
}
|
||||
|
||||
if config.PsFormat != `table {{.ID}}\t{{.Label "com.docker.label.cpu"}}` {
|
||||
t.Fatalf("Unknown ps format: %s\n", config.PsFormat)
|
||||
}
|
||||
|
||||
// Now save it and make sure it shows up in new form
|
||||
err = config.Save()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save: %q", err)
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadFile(filepath.Join(tmpHome, CONFIGFILE))
|
||||
if !strings.Contains(string(buf), `"psFormat":`) ||
|
||||
!strings.Contains(string(buf), "{{.ID}}") {
|
||||
t.Fatalf("Should have save in new form: %s", string(buf))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ docker-ps - List containers
|
|||
[**-q**|**--quiet**[=*false*]]
|
||||
[**-s**|**--size**[=*false*]]
|
||||
[**--since**[=*SINCE*]]
|
||||
[**-F**|**--format**=*"TEMPLATE"*]
|
||||
|
||||
|
||||
# DESCRIPTION
|
||||
|
@ -59,6 +60,20 @@ the running containers.
|
|||
**--since**=""
|
||||
Show only containers created since Id or Name, include non-running ones.
|
||||
|
||||
**-F**, **--format**=*"TEMPLATE"*
|
||||
Pretty-print containers using a Go template.
|
||||
Valid placeholders:
|
||||
.ID - Container ID
|
||||
.Image - Image ID
|
||||
.Command - Quoted command
|
||||
.CreatedAt - Time when the container was created.
|
||||
.RunningFor - Elapsed time since the container was started.
|
||||
.Ports - Exposed ports.
|
||||
.Status - Container status.
|
||||
.Size - Container disk size.
|
||||
.Labels - All labels asigned to the container.
|
||||
.Label - Value of a specific label for this container. For example `{{.Label "com.docker.swarm.cpu"}}`
|
||||
|
||||
# EXAMPLES
|
||||
# Display all containers, including non-running
|
||||
|
||||
|
@ -82,6 +97,32 @@ the running containers.
|
|||
# docker ps -a -q --filter=name=determined_torvalds
|
||||
c1d3b0166030
|
||||
|
||||
# Display containers with their commands
|
||||
|
||||
# docker ps --format "{{.ID}}: {{.Command}}"
|
||||
a87ecb4f327c: /bin/sh -c #(nop) MA
|
||||
01946d9d34d8: /bin/sh -c #(nop) MA
|
||||
c1d3b0166030: /bin/sh -c yum -y up
|
||||
41d50ecd2f57: /bin/sh -c #(nop) MA
|
||||
|
||||
# Display containers with their labels in a table
|
||||
|
||||
# docker ps --format "table {{.ID}}\t{{.Labels}}"
|
||||
CONTAINER ID LABELS
|
||||
a87ecb4f327c com.docker.swarm.node=ubuntu,com.docker.swarm.storage=ssd
|
||||
01946d9d34d8
|
||||
c1d3b0166030 com.docker.swarm.node=debian,com.docker.swarm.cpu=6
|
||||
41d50ecd2f57 com.docker.swarm.node=fedora,com.docker.swarm.cpu=3,com.docker.swarm.storage=ssd
|
||||
|
||||
# Display containers with their node label in a table
|
||||
|
||||
# docker ps --format 'table {{.ID}}\t{{(.Label "com.docker.swarm.node")}}'
|
||||
CONTAINER ID NODE
|
||||
a87ecb4f327c ubuntu
|
||||
01946d9d34d8
|
||||
c1d3b0166030 debian
|
||||
41d50ecd2f57 fedora
|
||||
|
||||
# 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 New Issue