cli: use custom annotation for aliases

Cobra allows for aliases to be defined for a command, but only allows these
to be defined at the same level (for example, `docker image ls` as alias for
`docker image list`). Our CLI has some commands that are available both as a
top-level shorthand as well as `docker <object> <verb>` subcommands. For example,
`docker ps` is a shorthand for `docker container ps` / `docker container ls`.

This patch introduces a custom "aliases" annotation that can be used to print
all available aliases for a command. While this requires these aliases to be
defined manually, in practice the list of aliases rarely changes, so maintenance
should be minimal.

As a convention, we could consider the first command in this list to be the
canonical command, so that we can use this information to add redirects in
our documentation in future.

Before this patch:

    docker images --help

    Usage:  docker images [OPTIONS] [REPOSITORY[:TAG]]

    List images

    Options:
      -a, --all             Show all images (default hides intermediate images)
      ...

With this patch:

    docker images --help

    Usage:  docker images [OPTIONS] [REPOSITORY[:TAG]]

    List images

    Aliases:
      docker image ls, docker image list, docker images

    Options:
      -a, --all             Show all images (default hides intermediate images)
      ...

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-06-28 10:52:25 +02:00
parent 05d288eb06
commit 80b1285fec
72 changed files with 212 additions and 1 deletions

View File

@ -31,6 +31,7 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p
opts.Common.InstallFlags(flags)
cobra.AddTemplateFunc("add", func(a, b int) int { return a + b })
cobra.AddTemplateFunc("hasAliases", hasAliases)
cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
cobra.AddTemplateFunc("hasTopCommands", hasTopCommands)
cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
@ -239,6 +240,10 @@ func isPlugin(cmd *cobra.Command) bool {
return cmd.Annotations[pluginmanager.CommandAnnotationPlugin] == "true"
}
func hasAliases(cmd *cobra.Command) bool {
return len(cmd.Aliases) > 0 || cmd.Annotations["aliases"] != ""
}
func hasSubCommands(cmd *cobra.Command) bool {
return len(operationSubCommands(cmd)) > 0
}
@ -263,6 +268,9 @@ func hasTopCommands(cmd *cobra.Command) bool {
// formatted as the full command as they're called (contrary to the default
// Aliases function, which only returns the subcommand).
func commandAliases(cmd *cobra.Command) string {
if cmd.Annotations["aliases"] != "" {
return cmd.Annotations["aliases"]
}
var parentPath string
if cmd.HasParent() {
parentPath = cmd.Parent().CommandPath() + " "
@ -411,7 +419,7 @@ EXPERIMENTAL:
https://docs.docker.com/go/experimental/
{{- end}}
{{- if gt .Aliases 0}}
{{- if hasAliases . }}
Aliases:
{{ commandAliases . }}

View File

@ -81,9 +81,18 @@ func TestInvalidPlugin(t *testing.T) {
func TestCommandAliases(t *testing.T) {
root := &cobra.Command{Use: "root"}
sub := &cobra.Command{Use: "subcommand", Aliases: []string{"alias1", "alias2"}}
sub2 := &cobra.Command{Use: "subcommand2", Annotations: map[string]string{"aliases": "root foo, root bar"}}
root.AddCommand(sub)
root.AddCommand(sub2)
assert.Equal(t, hasAliases(sub), true)
assert.Equal(t, commandAliases(sub), "root subcommand, root alias1, root alias2")
assert.Equal(t, hasAliases(sub2), true)
assert.Equal(t, commandAliases(sub2), "root foo, root bar")
sub.Annotations = map[string]string{"aliases": "custom alias, custom alias 2"}
assert.Equal(t, hasAliases(sub), true)
assert.Equal(t, commandAliases(sub), "custom alias, custom alias 2")
}
func TestDecoratedName(t *testing.T) {

View File

@ -55,6 +55,9 @@ func NewAttachCommand(dockerCli command.Cli) *cobra.Command {
opts.container = args[0]
return runAttach(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container attach, docker attach",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(container types.Container) bool {
return container.State != "paused"
}),

View File

@ -37,6 +37,9 @@ func NewCommitCommand(dockerCli command.Cli) *cobra.Command {
}
return runCommit(dockerCli, &options)
},
Annotations: map[string]string{
"aliases": "docker container commit, docker commit",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}

View File

@ -101,6 +101,9 @@ func NewCopyCommand(dockerCli command.Cli) *cobra.Command {
}
return runCopy(dockerCli, opts)
},
Annotations: map[string]string{
"aliases": "docker container cp, docker cp",
},
}
flags := cmd.Flags()

View File

@ -57,6 +57,9 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
}
return runCreate(dockerCli, cmd.Flags(), &options, copts)
},
Annotations: map[string]string{
"aliases": "docker container create, docker create",
},
ValidArgsFunction: completion.ImageNames(dockerCli),
}

View File

@ -27,6 +27,9 @@ func NewDiffCommand(dockerCli command.Cli) *cobra.Command {
opts.container = args[0]
return runDiff(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container diff, docker diff",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}
}

View File

@ -59,6 +59,7 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
}),
Annotations: map[string]string{
"category-top": "2",
"aliases": "docker container exec, docker exec",
},
}

View File

@ -28,6 +28,9 @@ func NewExportCommand(dockerCli command.Cli) *cobra.Command {
opts.container = args[0]
return runExport(dockerCli, opts)
},
Annotations: map[string]string{
"aliases": "docker container export, docker export",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true),
}

View File

@ -30,6 +30,9 @@ func NewKillCommand(dockerCli command.Cli) *cobra.Command {
opts.containers = args
return runKill(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container kill, docker kill",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}

View File

@ -40,6 +40,7 @@ func NewPsCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "3",
"aliases": "docker container ls, docker container list, docker container ps, docker ps",
},
ValidArgsFunction: completion.NoComplete,
}

View File

@ -35,6 +35,9 @@ func NewLogsCommand(dockerCli command.Cli) *cobra.Command {
opts.container = args[0]
return runLogs(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container logs, docker logs",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true),
}

View File

@ -29,6 +29,9 @@ func NewPauseCommand(dockerCli command.Cli) *cobra.Command {
opts.containers = args
return runPause(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container pause, docker pause",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(container types.Container) bool {
return container.State != "paused"
}),

View File

@ -35,6 +35,9 @@ func NewPortCommand(dockerCli command.Cli) *cobra.Command {
}
return runPort(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container port, docker port",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}
return cmd

View File

@ -30,6 +30,9 @@ func NewRenameCommand(dockerCli command.Cli) *cobra.Command {
opts.newName = args[1]
return runRename(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container rename, docker rename",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true),
}
return cmd

View File

@ -34,6 +34,9 @@ func NewRestartCommand(dockerCli command.Cli) *cobra.Command {
opts.timeoutChanged = cmd.Flags().Changed("time")
return runRestart(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container restart, docker restart",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true),
}

View File

@ -34,6 +34,9 @@ func NewRmCommand(dockerCli command.Cli) *cobra.Command {
opts.containers = args
return runRm(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container rm, docker rm",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true),
}

View File

@ -48,6 +48,7 @@ func NewRunCommand(dockerCli command.Cli) *cobra.Command {
ValidArgsFunction: completion.ImageNames(dockerCli),
Annotations: map[string]string{
"category-top": "1",
"aliases": "docker container run, docker run",
},
}

View File

@ -44,6 +44,9 @@ func NewStartCommand(dockerCli command.Cli) *cobra.Command {
opts.Containers = args
return RunStart(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container start, docker start",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true, func(container types.Container) bool {
return container.State == "exited" || container.State == "created"
}),

View File

@ -40,6 +40,9 @@ func NewStatsCommand(dockerCli command.Cli) *cobra.Command {
opts.containers = args
return runStats(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container stats, docker stats",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}

View File

@ -34,6 +34,9 @@ func NewStopCommand(dockerCli command.Cli) *cobra.Command {
opts.timeoutChanged = cmd.Flags().Changed("time")
return runStop(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container stop, docker stop",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}

View File

@ -31,6 +31,9 @@ func NewTopCommand(dockerCli command.Cli) *cobra.Command {
opts.args = args[1:]
return runTop(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container top, docker top",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}

View File

@ -29,6 +29,9 @@ func NewUnpauseCommand(dockerCli command.Cli) *cobra.Command {
opts.containers = args
return runUnpause(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container unpause, docker unpause",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(container types.Container) bool {
return container.State == "paused"
}),

View File

@ -49,6 +49,9 @@ func NewUpdateCommand(dockerCli command.Cli) *cobra.Command {
options.nFlag = cmd.Flags().NFlag()
return runUpdate(dockerCli, &options)
},
Annotations: map[string]string{
"aliases": "docker container update, docker update",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, true),
}

View File

@ -28,6 +28,9 @@ func NewWaitCommand(dockerCli command.Cli) *cobra.Command {
opts.containers = args
return runWait(dockerCli, &opts)
},
Annotations: map[string]string{
"aliases": "docker container wait, docker wait",
},
ValidArgsFunction: completion.ContainerNames(dockerCli, false),
}

View File

@ -107,6 +107,7 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "4",
"aliases": "docker image build, docker build, docker buildx build, docker builder build",
},
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveFilterDirs

View File

@ -31,6 +31,9 @@ func NewHistoryCommand(dockerCli command.Cli) *cobra.Command {
opts.image = args[0]
return runHistory(dockerCli, opts)
},
Annotations: map[string]string{
"aliases": "docker image history, docker history",
},
}
flags := cmd.Flags()

View File

@ -36,6 +36,9 @@ func NewImportCommand(dockerCli command.Cli) *cobra.Command {
}
return runImport(dockerCli, options)
},
Annotations: map[string]string{
"aliases": "docker image import, docker import",
},
}
flags := cmd.Flags()

View File

@ -39,6 +39,7 @@ func NewImagesCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "7",
"aliases": "docker image ls, docker image list, docker images",
},
}

View File

@ -29,6 +29,9 @@ func NewLoadCommand(dockerCli command.Cli) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
return runLoad(dockerCli, opts)
},
Annotations: map[string]string{
"aliases": "docker image load, docker load",
},
ValidArgsFunction: completion.NoComplete,
}

View File

@ -37,6 +37,7 @@ func NewPullCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "5",
"aliases": "docker image pull, docker pull",
},
ValidArgsFunction: completion.NoComplete,
}

View File

@ -38,6 +38,7 @@ func NewPushCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "6",
"aliases": "docker image push, docker push",
},
ValidArgsFunction: completion.ImageNames(dockerCli),
}

View File

@ -29,6 +29,9 @@ func NewRemoveCommand(dockerCli command.Cli) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
return runRemove(dockerCli, opts, args)
},
Annotations: map[string]string{
"aliases": "docker image rm, docker image remove, docker rmi",
},
}
flags := cmd.Flags()

View File

@ -28,6 +28,9 @@ func NewSaveCommand(dockerCli command.Cli) *cobra.Command {
opts.images = args
return RunSave(dockerCli, opts)
},
Annotations: map[string]string{
"aliases": "docker image save, docker save",
},
ValidArgsFunction: completion.ImageNames(dockerCli),
}

View File

@ -27,6 +27,9 @@ func NewTagCommand(dockerCli command.Cli) *cobra.Command {
opts.name = args[1]
return runTag(dockerCli, opts)
},
Annotations: map[string]string{
"aliases": "docker image tag, docker tag",
},
ValidArgsFunction: completion.ImageNames(dockerCli),
}

View File

@ -37,6 +37,9 @@ func NewEventsCommand(dockerCli command.Cli) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
return runEvents(dockerCli, &options)
},
Annotations: map[string]string{
"aliases": "docker system events, docker events",
},
ValidArgsFunction: completion.NoComplete,
}

View File

@ -57,6 +57,7 @@ func NewInfoCommand(dockerCli command.Cli) *cobra.Command {
},
Annotations: map[string]string{
"category-top": "12",
"aliases": "docker system info, docker info",
},
ValidArgsFunction: completion.NoComplete,
}

View File

@ -11,6 +11,9 @@ Usage: docker attach [OPTIONS] CONTAINER
Attach local standard input, output, and error streams to a running container
Aliases:
docker container attach, docker attach
Options:
--detach-keys string Override the key sequence for detaching a container
--help Print usage

View File

@ -11,6 +11,9 @@ Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
Aliases:
docker image build, docker build, docker buildx build, docker builder build
Options:
--add-host value Add a custom host-to-IP mapping (host:ip) (default [])
--build-arg value Set build-time variables (default [])

View File

@ -11,6 +11,9 @@ Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Aliases:
docker container commit, docker commit
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change value Apply Dockerfile instruction to the created image (default [])

View File

@ -17,6 +17,9 @@ and extract it to a directory destination in a container.
Use '-' as the destination to stream a tar archive of a
container source to stdout.
Aliases:
docker container cp, docker cp
Options:
-L, --follow-link Always follow symbol link in SRC_PATH
-a, --archive Archive mode (copy all uid/gid information)

View File

@ -13,6 +13,9 @@ Usage: docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
Create a new container
Aliases:
docker container create, docker create
Options:
--add-host value Add a custom host-to-IP mapping (host:ip) (default [])
-a, --attach value Attach to STDIN, STDOUT or STDERR (default [])

View File

@ -11,6 +11,9 @@ Usage: docker diff CONTAINER
Inspect changes to files or directories on a container's filesystem
Aliases:
docker container diff, docker diff
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker events [OPTIONS]
Get real time events from the server
Aliases:
docker system events, docker events
Options:
-f, --filter value Filter output based on conditions provided (default [])
--format string Format the output using the given Go template

View File

@ -11,6 +11,9 @@ Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Execute a command in a running container
Aliases:
docker container exec, docker exec
Options:
-d, --detach Detached mode: run command in the background
--detach-keys Override the key sequence for detaching a container

View File

@ -11,6 +11,9 @@ Usage: docker export [OPTIONS] CONTAINER
Export a container's filesystem as a tar archive
Aliases:
docker container export, docker export
Options:
--help Print usage
-o, --output string Write to a file, instead of STDOUT

View File

@ -11,6 +11,9 @@ Usage: docker history [OPTIONS] IMAGE
Show the history of an image
Aliases:
docker image history, docker history
Options:
--format string Pretty-print images using a Go template
--help Print usage

View File

@ -11,6 +11,9 @@ Usage: docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Aliases:
docker image ls, docker image list, docker images
Options:
-a, --all Show all images (default hides intermediate images)
--digests Show digests

View File

@ -11,6 +11,9 @@ Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
Import the contents from a tarball to create a filesystem image
Aliases:
docker image import, docker import
Options:
-c, --change value Apply Dockerfile instruction to the created image (default [])
--help Print usage

View File

@ -11,6 +11,9 @@ Usage: docker info [OPTIONS]
Display system-wide information
Aliases:
docker system info, docker info
Options:
-f, --format string Format the output using the given Go template
--help Print usage

View File

@ -11,6 +11,9 @@ Usage: docker kill [OPTIONS] CONTAINER [CONTAINER...]
Kill one or more running containers
Aliases:
docker container kill, docker kill
Options:
--help Print usage
-s, --signal string Signal to send to the container

View File

@ -12,6 +12,9 @@ Usage: docker load [OPTIONS]
Load an image or repository from a tar archive (even if compressed with gzip,
bzip2, or xz) from a file or STDIN.
Aliases:
docker image load, docker load
Options:
--help Print usage
-i, --input string Read from tar archive file, instead of STDIN.

View File

@ -11,6 +11,9 @@ Usage: docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Aliases:
docker container logs, docker logs
Options:
--details Show extra details provided to logs
-f, --follow Follow log output

View File

@ -11,6 +11,9 @@ Usage: docker pause CONTAINER [CONTAINER...]
Pause all processes within one or more containers
Aliases:
docker container pause, docker pause
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker port CONTAINER [PRIVATE_PORT[/PROTO]]
List port mappings or a specific mapping for the container
Aliases:
docker container port, docker port
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker ps [OPTIONS]
List containers
Aliases:
docker container ls, docker container list, docker container ps, docker ps
Options:
-a, --all Show all containers (default shows just running)
-f, --filter value Filter output based on conditions provided (default [])

View File

@ -11,6 +11,9 @@ Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Download an image from a registry
Aliases:
docker image pull, docker pull
Options:
-a, --all-tags Download all tagged images in the repository
--disable-content-trust Skip image verification (default true)

View File

@ -11,6 +11,9 @@ Usage: docker push [OPTIONS] NAME[:TAG]
Upload an image to a registry
Aliases:
docker image push, docker push
Options:
-a, --all-tags Push all tags of an image to the repository
--disable-content-trust Skip image signing (default true)

View File

@ -11,6 +11,9 @@ Usage: docker rename CONTAINER NEW_NAME
Rename a container
Aliases:
docker container rename, docker rename
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker restart [OPTIONS] CONTAINER [CONTAINER...]
Restart one or more containers
Aliases:
docker container restart, docker restart
Options:
-s, --signal string Signal to send to the container
-t, --time int Seconds to wait before killing the container

View File

@ -11,6 +11,9 @@ Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Aliases:
docker container rm, docker rm
Options:
-f, --force Force the removal of a running container (uses SIGKILL)
--help Print usage

View File

@ -11,6 +11,9 @@ Usage: docker rmi [OPTIONS] IMAGE [IMAGE...]
Remove one or more images
Aliases:
docker image rm, docker rmi
Options:
-f, --force Force removal of the image
--help Print usage

View File

@ -11,6 +11,9 @@ Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Create and run a new container from an image
Aliases:
docker container run, docker run
Options:
--add-host value Add a custom host-to-IP mapping (host:ip) (default [])
-a, --attach value Attach to STDIN, STDOUT or STDERR (default [])

View File

@ -11,6 +11,9 @@ Usage: docker save [OPTIONS] IMAGE [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
Aliases:
docker image save, docker save
Options:
--help Print usage
-o, --output string Write to a file, instead of STDOUT

View File

@ -11,6 +11,9 @@ Usage: docker start [OPTIONS] CONTAINER [CONTAINER...]
Start one or more stopped containers
Aliases:
docker container start, docker start
Options:
-a, --attach Attach STDOUT/STDERR and forward signals
--detach-keys string Override the key sequence for detaching a container

View File

@ -11,6 +11,9 @@ Usage: docker stats [OPTIONS] [CONTAINER...]
Display a live stream of container(s) resource usage statistics
Aliases:
docker container stats, docker stats
Options:
-a, --all Show all containers (default shows just running)
--format string Pretty-print images using a Go template

View File

@ -11,6 +11,9 @@ Usage: docker stop [OPTIONS] CONTAINER [CONTAINER...]
Stop one or more running containers
Aliases:
docker container stop, docker stop
Options:
-s, --signal string Signal to send to the container
-t, --time int Seconds to wait before killing the container

View File

@ -11,6 +11,9 @@ Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
Aliases:
docker image tag, docker tag
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker top CONTAINER [ps OPTIONS]
Display the running processes of a container
Aliases:
docker container top, docker top
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker unpause CONTAINER [CONTAINER...]
Unpause all processes within one or more containers
Aliases:
docker container unpause, docker unpause
Options:
--help Print usage
```

View File

@ -11,6 +11,9 @@ Usage: docker update [OPTIONS] CONTAINER [CONTAINER...]
Update configuration of one or more containers
Aliases:
docker container update, docker update
Options:
--blkio-weight uint16 Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
--cpu-period int Limit CPU CFS (Completely Fair Scheduler) period

View File

@ -11,6 +11,9 @@ Usage: docker wait CONTAINER [CONTAINER...]
Block until one or more containers stop, then print their exit codes
Aliases:
docker container wait, docker wait
Options:
--help Print usage
```