3 Rather Unknown Docker Commands That Will Help You in a Variety of Scenarios

If you're using Docker for a while you probably already have a simple and effective workflow tailored to you, which includes some of your favorite docker commands (subcommands to be technically correct).

For example, I used to remove the containers that are not running using a long command which looks like this docker container rm $(docker container ps -qf status=exited), it worked, obviously throwing an error whenever there were no dangling containers. This stopped one day when I found out that we also have a prune subcommand for containers! So now that long command has come down to a simple docker container prune.

The point is even though many of us have been using Docker for a while, there is the chance that some things might've gotten overlooked, or maybe even forgotten through time.

In this article, I'm going to give you three docker subcommands, that might be new to you, or you're not using them much but I think you should.

These sub-commands might also include their own sub-commands.

1. The system sub-command

Docker has a system command that gives you some system-level information related to docker. You have actually been using one of its subcommands for a while now. Remember docker info? This command is actually docker system info.

To know more about this subcommand and what it offers, run the --help option on it.

➟ docker system --help

Usage:  docker system COMMAND

Manage Docker

Commands:
  df          Show docker disk usage
  events      Get real time events from the server
  info        Display system-wide information
  prune       Remove unused data

Run 'docker system COMMAND --help' for more information on a command.

Let's go through each of these subcommands since I think they're all very critical.

Docker system df

Have you ever been in a situation where your server's disk space seemed to be nearly full? To inspect whether it's the containers (running/volumes) you probably have been using the du command directly on the data root.

Data root or data-root is the location where docker stores all the data related to its state. That includes but is not limited to images (layers), volumes, network related information, plugins.

Using du on the data root requires sudo access.

✗ du -h --max-depth=1 /var/lib/docker
du: cannot read directory '/var/lib/docker': Permission denied
4.0K    /var/lib/docker

Not only that, to explicitly know how much the volumes are allocating or the images, you'd have to run the command several times.

➟ sudo du -h --max-depth=0 /var/lib/docker/volumes && \
    sudo du -h --max-depth=0 /var/lib/docker/image && \
    sudo du -h --max-depth=0 /var/lib/docker/

A much better alternative is to call the docker system df command. This will automatically detect the data root and accordingly print all the information regards to the disk usage by Docker containers, images and volumes.

Here's what my current system shows (it's a new install)

➟ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          10        1         84.17MB   84.17MB (100%)
Containers      1         1         8.219MB   0B (0%)
Local Volumes   0         0         0B        0B
Build Cache     0         0         0B        0B

Docker system prune

If you ever wanted to remove (1) all unused networks, (2) dangling images, (3) stopped containers, (4) all unused volumes, there's a big chance you used, or are used to using four separate commands to achieve the job.

docker network prune && \
    docker image prune && \
    docker volume prune && \
    docker container prune

If you didn't previously know about container prune like me then the command gets even bigger. Well lucky for us, all of this can be done using just a simple command, namely docker system prune --volumes.

By default docker system prune doesn't remove the volumes, for that you need to use the --volumes option. This command additionally also clears the build cache for you.

You can use the -f option to avoid the (sometimes) annoying prompt. See the example below:

➟ docker system prune --volumes -f
Deleted Containers:
672d39c1a78969887f411ce9139e74e5b21c31fccf2bcf8c1190a9e166089ede

Deleted Networks:
Example
SSHnet
Dummy

Deleted Volumes:
dummy

Total reclaimed space: 0B

Other options include -a that removes all unused images, not just the dangling ones.

Docker system events

This command may not be useful all the time, but it's something I think everyone should be aware of.

docker system events or docker events for short gives you real-time events directly for the docker daemon (dockerd). This can help monitor certain events like when an image has been removed, for instance.

See the screenshot below to understand this better.

2. The context subcommand

This is another beautiful subcommand that not many are aware of as far as I know. A context to any docker command execution is a couple of key-value pairs, that includes but are not limited to the endpoint, host, maybe some config file, etc.

Once you have a context created, it can be reused later on.

One of the biggest practical use cases, especially for me has been creating separate contexts for the individual servers that I have docker running. Since most of my work revolves around it, instead of logging into the server every single time, I use my local client with the remove docker server over SSH.

How to Set Up Remote Access to Docker Daemon [Detailed Guide]
Don’t want to ssh into remote server and then run docker commands? You can set up remote docker access that has other benefits too.

Let me show you how I achieve this with docker contexts.

First I have a server deployed on Linode, that has docker running. If I were to access the remote docker daemon, without contexts, I'd be using a command like the following

➟ docker --host ssh://debdut@194.195.116.210:7770 ps
CONTAINER ID   IMAGE                                    COMMAND                  CREATED       STATUS       PORTS                                                                      NAMES
bb4fa8390ab7   jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   2 hours ago   Up 2 hours                                                                              reverse-proxy_letsencrypt_1
ccdda507facb   jwilder/nginx-proxy                      "/app/docker-entrypo…"   2 hours ago   Up 2 hours   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   reverse-proxy_reverse_proxy_1

So to access the remote daemon either I'd have to alias docker to docker --host ssh://debdut@194.195.116.210:7770, or use an environment variable DOCKER_HOST. But these make switching to other hosts very difficult. An easier alternative is to just create a context.

The following command creates a context named remote, for a docker endpoint with a different host than the local.

docker context create remote --description "Remote docker server" --docker "host=ssh://debdut@194.195.116.210:7770"

The output looks like this:

➟ docker context create remote --description "Remote docker server" --docker "host=ssh://debdut@194.195.116.210:7770"
remote
Successfully created context "remote"

Now you can either use the -c option with docker if you want to check something quickly or for repeated operations, change the context to this new one.

With the -c option:

➟ docker -c remote ps
CONTAINER ID   IMAGE                                    COMMAND                  CREATED       STATUS       PORTS                                                                      NAMES
bb4fa8390ab7   jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   2 hours ago   Up 2 hours                                                                              reverse-proxy_letsencrypt_1
ccdda507facb   jwilder/nginx-proxy                      "/app/docker-entrypo…"   2 hours ago   Up 2 hours   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   reverse-proxy_reverse_proxy_1

With docker context use [CONTEXT_NAME]:

➟ docker context use remote
remote
Current context is now "remote"
~ 
➟ docker ps
CONTAINER ID   IMAGE                                    COMMAND                  CREATED       STATUS       PORTS                                                                      NAMES
bb4fa8390ab7   jrcs/letsencrypt-nginx-proxy-companion   "/bin/bash /app/entr…"   2 hours ago   Up 2 hours                                                                              reverse-proxy_letsencrypt_1
ccdda507facb   jwilder/nginx-proxy                      "/app/docker-entrypo…"   2 hours ago   Up 2 hours   0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   reverse-proxy_reverse_proxy_1

To get out of the context, use the use subcommand with default for the context name:

➟ docker context use default
default
Current context is now "default"
~ 
➟ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

3. The pause & unpause subcommand

Big deployment (applications) are now divided into multiple components, better known as micro-services. When you deploy them using something like docker-compose, sometimes what happens is that one component starts up before the one[s] it depends on. This is a problem because since its dependency (or dependencies) hasn't started yet, this component is going to fail to start.

You can mitigate this problem by using restart policies in Docker, but they don't prevent flooding the log with failed attempts. What I used to do at the beginning is just stop the container/service until the dependency has completely started up.

A better way is to just pause the container for a while, and once the necessary service[s] has successfully come up, you can unpause the container and everything will move forward from there just fine.

Although containers are fast to spin up, this is an even faster way to counter such an issue.

The syntax for pause and unpause is quite simple.

docker pause [CONTAINER_NAME|ID]
docker unpause [CONTAINER_NAME|ID]

That concludes this article for now. If I find any more such commands, useful or interesting, I'll update this article accordingly.

Do you have a Docker command that you think should've been on this list? Do let me know in the comments down below.