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:
- 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. - 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:
- Leverage deep learning in IBM Cloud Functions
- IBM Data Asset eXchange
- IBM Model Asset eXchange
- Deploy deep learning models as a web microservice in minutes - Silicon Valley Code Camp (October 19-20 2019)
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:
- I must say, one of the best Docker presentations I've seen thus far is Jerome Petazzoni's 2015 talk, Cgroups, namespaces, and beyond: what are containers made from?
- I've also started watching a much longer talk of Jerome's, his three-hour Introduction to Docker and Containers from PyCon 2016. It's accompanied by an INSANE resource at https://container.training/, with videos, previous workshops and presentations, and lecture slides for self-paced review. Enjoy!
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 😎👉🏾:
- Deploying my first service on Kubernetes: Demystifying ingress
- Pods, services, deployments... what do I use when?
Hit the heart button, share this DEV article with someone you care about, and see ya soon! <3
Top comments (0)