The Whale in the Refrigerator — An Introduction to Docker

Michael Mucciarone
Capital One Tech
Published in
10 min readFeb 26, 2019
An old refrigerator. Pictures and drawings of whales are attached with alphabet magnets. The magnets spell out D-O-C-K-E-R.

If you’ve spent any time in the DevOps realm, you’ve probably heard of Docker, and you’ve definitely heard of “containers”. If you’re just starting out in DevOps or want to know what Docker is and how containers work, then please allow me to enlighten you! I’m a DevOps engineer and a Docker enthusiast that has been using Docker for about five years to build everything from small containerized utilities to production quality containers. And I love talking about Docker. Let’s start at the beginning…

What is a Container?

It’s impossible to talk about Docker without a higher level understanding of what a container is. A container (in this context) is an isolated user-space instance. Usually this isolation is both from the host computer’s file system and from its networking, meaning that by default, any processes that run in the container do not have direct access to the host computer’s resources. The result is that if you are interacting with a shell that is running inside a container, you will not (again, by default) have access to any of the executables on the host system.

For comparison, let’s take the example of a refrigerator. The refrigerator runs constantly and maintains a given air temperature and humidity inside. Now, say you want to store some leftovers in the refrigerator. You place those leftovers in a plastic container and place that container in the refrigerator. The container isolates the leftovers from the rest of the items in the refrigerator and isolates the rest of the refrigerator from the container. The container does not have any mechanism for cooling the leftovers, it re-uses the cooling resources of the refrigerator. Now say you leave the container in the refrigerator too long and mold manages to get into the container. The container is now protecting the rest of the items in the refrigerator from the mold, ensuring that all the food in the refrigerator is not spoiled simply because one item went bad.

What is Docker (and What Makes it Special)?

Hopefully, the above provided a high level understanding of what a container is. So what is Docker? Docker is a containerization platform that has become the de-facto standard for containerization in the datacenter. However, there is more to Docker than just containers. The Docker Command Line Interface and associated GUIs contain tools for easily storing, transporting, building, inspecting, and running container images — which are the basic unit of distribution for Docker — either as singular containers, groups of containers, or on orchestrated container clusters.

A Cartoon whale with the word “docker” which is the current docker logo as of 2020.

If you’re thinking that this sounds a lot like virtualization — that is, running a Virtual Machine (VM) inside a host operating system — then you are correct. Docker has a lot in common with Virtual Machines, at least on the surface. The advantage of containers in general, and Docker specifically, is system resource usage. As described in the refrigerator example above, a container reuses certain parts and services of the host OS that can be shared. Whereas a VM has to run a complete builds of any given guest OS — from kernel to user interface, bringing with it all of the disk and memory overhead that the guest OS introduces. This allows Docker containers to start much faster than a VM and causes them to use significantly fewer system resources.

A diagram comparing Virtual machines to Docker Containers.

Oh Oh, I Speak Whale!

Every software tool on the market has a lexicon of terms that have specific meanings in the context of that tool. Docker is no different. Here are two terms you will hear a lot when dealing with Docker.

  • Image or “Container Image”: A lightweight, stand-alone, executable package that includes everything needed to run a piece of software, including the code, runtime, libraries, environment variables, interpreters, and configuration files
  • Container: A runtime instance of an image — what the image becomes in memory when actually executed

Practical Benefits of Docker

Running Servers

There are several benefits to the containerization model, many of which are well beyond the scope of this article. However, one of these is software installation, upgrading, and removal. Let’s take a web server as an example.

Traditionally you install your web server of choice using your operating system’s package manager. This will install the web server executable, plus lots of other files, libraries, and other requirements to run that web server software, plus maybe some management utilities and/or plugins. Fast forward about six months when an upgrade is available for the web server. You install that upgrade via the package manager. Then you find that the new web server version breaks your website. So you roll it back, but in order to do that you have to uninstall the currently installed version of the web server. You can remove it, again using the OS package management tools, but more than likely you’ll leave residual files and libraries all over your disk, not to mention the potential for data loss.

With Docker, the installation and removal process are quite different. Almost all of the major web servers are available as official Docker images from Docker Hub. You simply pull a Docker image of whatever web server you would like to run to your local host (e.g. docker image pull nginx:latest), run it, and now you have a web server. When you need to upgrade, you simply pull the latest build, remove the old web server container, and start up the new one. Need to roll back? Just revert back to the older image. When you no longer need to run a web server on this host, simply remove the image (e.g. docker image remove nginx:latest). There is nothing to uninstall because all of the web server executables were inside the Docker image, and your system does not have any extra libraries or other files strewn about the filesystem.

Development

Another practical use of Docker is for development. Docker can be run on any modern desktop OS and provides the same functionality as on a Linux Server. The implication of this is that any Docker image can be run locally on your laptop or desktop, giving you easy access to your target architecture.

For example, let’s say your target architecture includes a Redis cache. If you need to write code that talks to a Redis Cache you could spin up a VM in the Cloud, install Redis and make sure that the security groups allow you to talk to it, make a note of its FQDN or IP address, and then start using it for development. Or, you could just docker image pull redis , docker container run redis and have a Redis cache running locally on your development computer. When you are finished with the Redis cache there is no need to uninstall or clean up that Redis installation, simply destroy the Redis container and remove the Redis image.

Docker Setup

Docker provides free installers for both Macintosh and Windows computers. Grab the “stable” version of the installer and install it. If you run into any problems, refer to those pages linked above for troubleshooting procedures.

The docker desktop preferences showing proxy configuration.

Once the installation is complete, test that it is working properly by running docker run hello-world in a terminal. Assuming your connection to the internet is unfettered, you should see Docker pull an image from Docker Hub called “hello world” and some boilerplate text should be printed to the terminal. If the image pull seems to hang, or if you’re behind a corporate proxy, you may need to edit Docker’s proxy information.

Open the preferences dialog by clicking on the Docker whale icon in the menu bar (Mac) or system tray (Windows) and selecting “Preferences…” then choosing the “Proxies” tab. Then try to run docker run hello-world again. If it still is not working, have a look at the documentation on those pages linked above.

Exercise: Run a Web Server

So we have Docker running now, let’s do something with it.

In this instance, we’re going to pull a Docker image of a Web Server (Nginx), start the Web Server, and verify that it’s working correctly. This will cover the following Docker commands:

> docker image pull

> docker image list

> docker image rm

> docker container run

> docker container stop

> docker container rm

Part 1: Pull the Image

I’m going to assume you have Docker running correctly on your computer. If not, please refer to the links above for your platform. The first step here is to run some kind of terminal, either Terminal or iTerm2 on MacOS, or CMD or PowerShell on Windows.

Once in a terminal, run this command:

> docker image pull nginx

You should see Docker begin pulling the image from Docker Hub. This should not take long, as the official Nginx image is relatively small.

Once this finishes and you have your prompt back, run this command:

> docker image list

You should see something like this:

A line of terminal text showing the output of the command `docker image list`.

Part 2: Run the Image

Your shiny new Nginx image has been downloaded, but it doesn’t do us any good until we run it.

To start the Nginx web server run this command:

> docker container run -d -p 80:80 nginx:latest

Before we go any further, let me break that command down for you, because I introduced some new command line switches that are important.

A diagram of the parts of the docker run cli command
  • docker container run = the base Docker command
  • -d = detach (i.e. send to background)
  • -p 80:80 = publish (i.e. attach ports from the host to the container)
  • The pattern for the publish switch is host:container or outside:inside
  • This is the magic that makes the container accessible
  • nginx:latest = image name

When you run the command above, assuming everything happened the way it’s supposed to, Docker should return a what looks like a random string of numbers like this:

de3a09f56fbd4d1d6c5cf5c7b43ac42257bdc7a92f3e7cccde42d9f07027f961

This is the unique ID for the container. There are many ways to identify/specify a container, but we’ll cover those in a future article.

Now that you’ve started the Nginx container, let’s check to make sure it’s working correctly. In a web browser (or using curl), navigate to http://localhost:80. You should get the standard Nginx welcome page:

A picture of the default web page served by a new installation of nginx.

Congratulations! You have just run your first Docker container.

Part 3: Cleanup

So now we’re done with this Nginx container. I would be remiss if I didn’t show you how to clean up after yourself. To stop this Docker container we need to know its ID. You could have noted it from above, but there is an easier way.

Execute this command:

> docker container ls

You should get something like this back:

An image of a terminal displaying the output of the command `docker ps -a`

The Container ID is on the left (20fe68eb05e5) and the auto-generated name (affectionate_davanci) is on the right. Either of these can be used to stop and destroy the container.

To Stop the container:

> docker stop <container ID or container name>

Now if you try to access http://localhost:80, the browser will timeout. That said, the Docker container is not actually gone, we’ve only “stopped” it. Execute the container list command again:

> docker container list

You should only get the header row back, meaning there are no “running” containers. Now execute this command:

> docker container list -a

The -a switch tells Docker to show you all containers, running and stopped. You should see your Nginx container, but under status it should say something like “Exited (0) About a minute ago”. Let’s get rid of that container forever.

Run this command:

> docker container rm <container id or container name>> docker container list -a

The Nginx container should now be gone. That said, the Nginx image is still there.

> docker image ls

This should show you the same Docker image we pulled earlier. To delete this image:

> docker image rm nginx:latest> docker image ls

The result should now be just the header rows, because there should be no Docker images remaining on your system.

Conclusion

In this article we talked a little about the theory behind containers, and the practical execution of containers using Docker. We installed Docker and ran a web server on our computer, and then we cleaned up any residual footprint on the computer.

I hope you’ve enjoyed this article and gotten at least a basic idea of what Docker is and why you would want to use it. If you did, please watch for follow up articles about more advanced Docker topics, including building Docker images and Dockerfiles.

These opinions are those of the author. Unless noted otherwise in this post, Capital One is not affiliated with, nor is it endorsed by any of the companies mentioned. All trademarks and other intellectual property used or displayed are the ownership of their respective owners. This article is © 2019 Capital One.

--

--

Michael Mucciarone
Capital One Tech

Devops Engineer; Artist at heart; Technologist by day. Container and DevOps Enthusiast with a side of UI/UX designer and a degree in Music.