Can I alias a subcommand? (shortening the output of `docker ps`)

The docker command has a ps sub-command that emits very long lines:

$ docker ps -a
CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS                      PORTS                                                                                                                                                                                                                                                                                                        NAMES
6e8ec8a16da4        waisbrot/wait:latest              "/wait"                  4 minutes ago       Exited (0) 4 minutes ago                                                                                                                                                                                                                                                                                                                 wait-for-janus-test
9dbf0739561f        whoop/downsampler:master          "./run.bash"             4 minutes ago       Up 4 minutes                0.0.0.0:32855->4369/tcp, 0.0.0.0:32854->9100/tcp, 0.0.0.0:32853->9101/tcp, 0.0.0.0:32852->9102/tcp, 0.0.0.0:32851->9103/tcp, 0.0.0.0:32850->9104/tcp, 0.0.0.0:32849->9105/tcp, 0.0.0.0:32848->9106/tcp, 0.0.0.0:32847->9107/tcp, 0.0.0.0:32846->9108/tcp, 0.0.0.0:32845->9109/tcp, 0.0.0.0:32844->9110/tcp   metrics-downsampler-test
6cf56623bb48        whoop/janus:master                "./start.bash"           4 minutes ago       Up 4 minutes                0.0.0.0:32843->80/tcp                                                                                                                                                                                                                                                                                        janus-test
882b50303d54        whoop/recalculator:master         "./run.bash"             4 minutes ago       Exited (1) 4 minutes ago                                                                                                                                                                                                                                                                                                                 internum-test

It can be instructed to output only specific columns:

docker ps --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}"

I'd like to be able to say docker ps and get the --format "table..." argument added on for me. Is there a nice way to do this?

I know I could say

alias dp='docker ps --format ...'

but I'd prefer to keep the sub-command.

I'm using zsh as my shell.


Solution 1:

You can wrap docker in a function that checks for the specific subcommand and passes everything else through. (The below will actually work with not just zsh, but any POSIX-compliant shell -- a category to which zsh doesn't quite belong).

docker() {
  case $1 in
    ps)
      shift
      command docker ps --format 'table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}' "$@"
      ;;
    *)
      command docker "$@";;
  esac
}

If you wanted a more generic wrapper function (that doesn't need to know about your specific desired ps logic), that could be done as follows (note that this version is not compatible with baseline POSIX sh due to its use of local; however, this is an extension implemented even by ash and its derivatives):

docker() {
  local cmd=$1; shift
  if command -v "docker_$cmd" >/dev/null 2>/dev/null; then
    "docker_$cmd" "$@"
  else
    command docker "$cmd" "$@"
  fi
}

...after which any subcommand can have its own functions defined, without the wrapper needing to be modified to know about them (you could also create a script in the PATH named docker_ps, or provide the command in any other manner you choose):

docker_ps() {
  command docker ps --format 'table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}' "$@"
}

Solution 2:

You can alias subcommands. With aliasing, you still get the nice zsh completions as if you were typing the full command. That's why I prefer them over functions.

The equivalent of your alias is:

alias dp='docker ps --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}'\t{{.Status}}"

But the full commands seem to now be recommended, and ls has replaced ps, which makes your alias now:

alias dp='docker container ls --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}'\t{{.Status}}"

It's nice to have docker aliases for everything. For this, I've been working on a set of comprehensive aliases, which would have your alias as something like:

alias ddcls='docker container ls --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}"

Solution 3:

Using Docker Config

Since this is fundamentally a docker questions, not a bash question, you don't even need an alias. Docker CLI allows you to customize these commands in your own config file! From this great tip from Container 42:

  1. Create or find your docker config file (if you've ever used docker login it should already be created.

    ~/.docker/config.json
    
  2. Then add the default formatting for docker to use every time it runs the ps command as a top level property in the config:

    {
        "psFormat": "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}",
    }
    
  3. Then just run docker ps like normal:

    docker ps

PS Format

Docker uses go templates and has a list of the valid placeholders:

Command Description
.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.
.Names Container names.
.Labels All labels assigned to the container.
.Label Value of a specific label for this container.
.Mounts Names of the volumes mounted in this container.
.Networks Names of the networks attached to this container.

Alternative Solutions / Threads

  • Github Issues
    • Default "docker ps" output is too wide
    • docker ps output is so long it's unreadable
  • Third Party Commands
    • ctop - Top-like interface for container metrics
    • docker-pretty-ps - beautiful, colored, long output log
    • dockerps - A better docker ps