docker learn #05: An Interesting --Help Quest

alexoeducative

Alex Ortiz

Posted on November 9, 2019

docker learn #05: An Interesting --Help Quest

This week, I wanted to poke around the Docker command line interface (CLI) to see how it can help me troubleshoot something or accomplish a goal. A few weeks ago as I was reading the very awesome book Docker Up & Running: Shipping Reliable Containers in Production by Sean P. Kane and Karl Matthias, I scribbled down a note next to a command. The scribble was, "What does --rm do?".

What does --rm do?

If you've already created a docker container and you want to manually remove it from your host, you can use the command docker rm <containername>.

But if what you want to do is use a single command to instruct the docker daemon to do three things—

1) pull an image,
2) create and run a container from that image, AND
3) remove the container right after

—then you can use docker run --rm.

Last week, I ran docker run ubuntu, which pulled the ubuntu:latest image, ran an instance (container) of that image with the command /bin/bash, and exited the container afterwards. Recall that this happens because Ubuntu is not an application or process but rather a base operating system image, so by design the ensuing container doesn't have any process running inside and is therefore terminated fractions of a second after it runs. But we were still able to double-check that the container indeed ran by typing docker ps -a.

However, let's see what happens if we use an alternative command with the --rm option:

docker run --rm ubuntu

What does this do? Let's find out by using Docker's insanely helpful --help option in the CLI.

When to gladly ask for --help

If we type docker run --help, the inline Docker manual tells us that the --rm flag will "automatically remove the container when it exits".

We can check for this because neither docker ps nor docker ps -a will list any container. But this begs the question: how can we tell the difference between "never having run any containers" and "having run containers that have since been deleted (or automatically removed)"?

Let's see if docker --help can give us such clues.

First, try running docker --help in your CLI. That will print the following:

$ docker --help

Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/root/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and
                           default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/root/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/root/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/root/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  app*        Docker Application (Docker Inc., v0.8.0)
  builder     Manage builds
  checkpoint  Manage checkpoints
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  manifest    Manage Docker image manifests and manifest lists
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  deploy      Deploy a new stack or update an existing stack
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Our goal is to figure out if there's a command in Docker that will show us a historical record of any containers that we previously ran, even if they were eventually deleted. So what we want to do is look for clues in the --help printout as to which command may help us display such a record.

Unfortunately for us, none of the Options in the list seem relevant to this quest. But in the Management Commands section, container looks promising.

So let's run docker container --help to drill down on what the container command does. Here's the output:

$ docker container --help

Usage:  docker container COMMAND

Manage containers

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  inspect     Display detailed information on one or more containers
  kill        Kill one or more running containers
  logs        Fetch the logs of a container
  ls          List containers
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  prune       Remove all stopped containers
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  run         Run a command in a new container
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

Ah! The container command is used to manage containers, which we can do by using all the commands listed just above. Among them, the inspect and logs commands initially appear to have potential. Sadly, they won't help either: we don't actually know the name or container ID of a container to refer these commands to. Alone, docker container inspect and docker container logs won't actually turn up anything. Neither will docker container ls, since there are no containers running.

In the main list of commands above, I discovered a command I hadn't used before: docker info. In addition to running docker ps -a, we can use docker info to confirm that no containers are running. It will list, among much else, the following:

$ docker info

[...]

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 1

[...]

So yea. We have one image (i.e., ubuntu:latest) running, but zero containers. With zero containers running, and no containers that ran but have not yet been deleted, we can't retrieve a container ID, which is necessary to use the inspect or logs command.

We are at a dead end.

Where to, From Here?

What we need is a list of activity that will display the container ID of the container that was created and exited when we first ran docker run --rm ubuntu above. However, none of the commands explored above, or found through the --help option, seem to do that.

At this point, one has to wonder if our assumption is even correct: does Docker even keep a log of containers that ran in the past (or during the current session) but no longer exist? On the one hand, this would be useful, to be able to distinguish "containers that happened" yet are no longer visible from "containers that never happened". If the daemon doesn't know the difference, then neither can we.

Being at this impasse, if I Google, "how to list the last docker container that ran", I only find two things that offer clues as to possible next steps:

  1. Some folks who wished to restore an accidentally deleted container have been able to do so by navigating to the directory /var/lib/docker/volumes/<containerIDfolder>/_data. I don't know how to do that yet, though.
  2. Docker's documentation describes the interplay between the local storage area of a running container and the /data directory on a Docker host

But alas, we are once again out of time for this week's post. This has been a great way to get to know the Docker CLI and how to leverage docker --help to quickly read the manual when attempting to solve a basic problem.

Great learning exercise! :)

This Week's Docker Answer Roundup

I'm back on my Q&A grind. Here are a few questions I answered this week.

On deploying AI models using containers

Q: How can I deploy AI models using Kubernetes?

Here's my answer:

For this question, you might find inspiration in some of the work being done to run ML models as microservices using a combination of Python, Flask, Docker, IBM’s Data Asset Exchange (DAX) network for open source data sets, IBM’s Model Asset Exchange (MAX) for open source deep learning models, and cloud-based Functions-as-a-Service (FaaS) platforms such as IBM’s own OpenWhisk.

What Docker does in this context is provide the containers and container runtime engine within which to perform certain aspects of training and using your models. If you have a need to run multiple, interacting containers, you might then use a container orchestrator such as Kubernetes. But the details will vary by your use case.

(The reason I say inspiration above is that there may be other approaches to doing something similar for what you want. Whereas the IBM approach is obviously targeted at enterprise uses of AI models, perhaps what you have in mind isn’t aimed at enterprise use cases. Nonetheless, the approach may offer you clues as to how you can go about doing what you’d like to do with containers).

Check out the following resources to see if there’s something helpful there:

And here’s the recording of the presentation in the last link above (the lecture slides are in the comments of the video - see “Session Materials”):

On using multiple containers for a web app

Q: Would you put the frontend and the backend of a web app in different docker containers?

Here's my answer:

Ideally and in many scenarios, yes. One of the software design practices that Docker is suited to (and subtly enforces) is the isolation of processes in an application stack. This helps with long-term scalability, especially if you anticipate your app being used in a way that requires running thousands of containers or more. Since a Docker container is a single, short-lived instance of a single task, process, or application, then it might make more sense to separate the front-end component from the back-end one(s). For example:

  • NodeJS in one container, with a MySQL database in another
  • PHP running in one container, nginx running in a second container, and MariaDB running in a third
  • A container with your front-end, another container with a cache service like Redis, and a database like MongoDB or CouchDB in yet another

In all of these scenarios involving multiple containers that are all necessary for your app to work, you’ll likely need a container orchestrator such as Docker Compose, Mesos, or Kubernetes.
Hope that helps.

On the future of container virtualization

Q: Do you see Windows containers as the next step in the evolution in virtualization or is it something that may fade away?

Here's my answer:

I’ll answer this more generally. With technology, it’s so hard to make predictions. Sure bets don’t always work out, and relative unknowns can become dominant forces over time. Within the span of 24–36 months, certain technologies and products can go from low adoption rates to rapid growth and eventually scale. So looking at the current state doesn’t help us much in anticipating the future; nobody can say for certain if Windows containers or Windows container runtime engines will or won’t experience rapid adoption in the future or become the go-to technology for OS-level virtualization. Just because something like 99% of the container ecosystem today is Linux-based doesn’t mean that this can’t change.

However, from what I’ve learned about containers and the container ecosystem—and I’m still at the very early stages of my learning—a few things are worth noting:

  • Technologies that experience rapid adoption usually benefit from a lot of work that came before it. This is true in every tech space, but here are two examples involving containers.
    • Docker has been a very successful container runtime engine, but its success came after lot of work by a lot of companies had been done on Linux kernels and containers. Perhaps there is foundational work being done today on Windows containers and Windows container runtime engines that isn’t visible to the mainstream but that will someday be looked upon as an example of why Windows containers became wildly successful.
    • Kubernetes has gained immense popularity as a Linux container orchestrator, but Google was working on Kubernetes for many years and was running millions of containers with it before it open-sourced the project. Years later (today), Kubernetes seems like the container orchestrator. But perhaps Titus (Netflix’s orchestrator) will be the go-to orchestrator for tomorrow. Who’s to say that an orchestrator natively based on Windows containers won’t become the Kubernetes or Titus of tomorrow?
  • Communities and network effects are wonderful, interesting drivers of product adoption. For instance, Facebook launched in 2004. It’s just fifteen years old. In a mere five 36-month timespans, it’s become the #6 most valuable company in the world and one of the most valuable companies of all time. It became that valuable this quickly due to its rapid adoption, the nature of networks and communities, and other just-in-time factors such as a rise in mobile phones, the reduced cost of telecommunications infrastructure, and new trends in how we consume media
    • By analogy, Docker and Kubernetes have enjoyed relatively rapid adoption cycles within their user communities. This is in part because Docker and Kubernetes solved a problem for a large addressable market of developers, engineers, and businesses. It’s likely also the case that these two technologies have benefited from good timing, emerging at a time when variables external to them have nevertheless positively impacted their adoption curves. If Windows container and container runtime tools emerge under analogous circumstances, then who knows what will happen

In summary, it isn’t inconceivable to imagine that in the next 5–10 years, a useful Windows container technology could emerge just as the market is ready for it. I’m not saying that it will happen, but I’m saying that it’s unrealistic to think that it can’t. Businesses tend to respond to the behaviors and expectations of their consumers. Technologies tend towards addressing the needs and requirements that arise because of this. So the evolution of containers—be that with respect to Linux, Windows, or anything else—will likely be influenced by the interplay between these two factors.

On image registries

Q: Where does Kubernetes pull images from?

Here's my answer:

Since Kubernetes is a container orchestrator and containers are built from container images (such as a Docker image), the images pulled by Kubernetes are also stored in a public or private container image registry. The technical documentation for Kubernetes says that you “can create your Docker image and push it to a registry before referring to it in a Kubernetes pod”.

Examples of image registries include Docker Hub, Docker Registry, Docker Trusted Registry (DTR) for enterprise, Google Container Registry, Amazon Elastic Container Registry (Amazon ECR), and many others. These all work with Kubernetes, so you can refer your images to your Kubernetes pods accordingly, pulling from a private registry if necessary.

On docker push

Q: How do I push an image to Docker Hub?

Here's my answer:

This is typically accomplished from the Docker client with the following command: docker push. What this command does, per Docker’s technical documentation, is to “push an image or a repository to a registry”. You can push an image to a public image repository such as Docker Hub, or to a private registry (see here for another answer of mine which references several public and private image repos).

On whether or not programmers should learn about orchestrators

Q: If you work in programming, should you learn Kubernetes?

Here's my answer:

This really depends on what you’d like to accomplish and if your programming work will require deploying containerized applications. If that’s the case, then learning about Docker may be a good investment of time, as that’s by far the most popular container runtime engine today. Docker is also heavily architected into Kubernetes. However, working with Kubernetes is a highly specialized skill and will likely take time to learn. If you do go in that direction, consider this resource.

I do hear that being able to debug and test your code in production with containers is a valuable skill to master, so if you plan to use Linux containers as part of your application stacks, then investing in learning Docker is likely a great idea.

Helpful Resources

These may be of service to you:


And that about does it for this week's docker learn. Thanks for spending some of your time with me, my learning, and my series! Have an awesome weekend, everyone!

docker shoutout

My Educative team runs a pretty awesome blog. Not only do we interview amazing Educative Authors like C# legend Eric Lippert, but also sometimes we have guest blog posts on topics that—you guessed it—relate to container technologies. Two of our guest articles have been by Microsoft Developer Advocate and Docker Captain Scott Coulton. The two pieces are about Kubernetes, and since this week I answered a few K8s-related Docker questions, go ahead and also read Scott's Educative posts if you so fancy 😎👉🏾:

Hit the heart button, share this DEV article with someone you care about, and see ya soon! <3

💖 💪 🙅 🚩
alexoeducative
Alex Ortiz

Posted on November 9, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related