This is part one of five in my Use Docker to create a local WordPress development environment tutorial.
The two most important terms to understand with Docker are images and containers. Some people use the terms interchangeably, but they are not. I could try and explain it, but Docker already did a better job:
Fundamentally, a container is nothing but a running process, with some added encapsulation features applied to it in order to keep it isolated from the host and from other containers. One of the most important aspects of container isolation is that each container interacts with its own private filesystem; this filesystem is provided by a Docker image. An image includes everything needed to run an application – the code or binary, runtimes, dependencies, and any other filesystem objects required.Docker.com
You can alter a container while it is running. If you want to persist the changes that you make to a container you can create a new image from the container and commit it to a Docker registry.
There are many Docker registries. The main one is hub.docker.com, where you can go to search for Docker images you would like to work with. You can set up your own registry (you can even do it with a container), and your Docker installation includes a local registry.
Your first Docker command
Before you perform anything in this tutorial, Docker needs to be running. In my case, that’s Docker Desktop for Mac. If it’s not running, any Docker command will produce an error. There is a Docker icon in the menu bar, but if I ever need to check if Docker is running with my most used Docker commands (more on that soon).
$ docker ps -a
This is the command to list all of your Docker containers. Since you should not have any Docker containers, you should only see the header row for the list.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Recently I was learning about Bash scripting on LinkedIn Learning. I decided to do my work in a container so as not to alter any of the configurations for the command line on my local machine (where I use Zsh instead of Bash). This basic command will “pull” – or download – an image from the Docker Hub registry, run it, and enter the container to use the Bash shell.
$ docker run -ti ubuntu:latest bash
docker: Use the Docker application.
run: The run command pulls the image from Docker Hub and runs it.
-toption creates a pseudo TTY terminal with which to communicate with the container. The
-ioption makes it interactive. I think of this option as “terminal interactive.”
ubuntu:latest: The string to the left of the colon specifies the image; the version or tag is to the right. This downloads an image of the latest Docker image for Ubuntu. If you just used
ubuntu, it would default to getting the latest version. If you wanted an older version you could specify
bash: The bash command gives you a shell in the container. It works with the
When you run that command, the output looks like this:
$ docker run -ti ubuntu:latest bash Unable to find image 'ubuntu:latest' locally latest: Pulling from library/ubuntu a4a2a29f9ba4: Pull complete 127c9761dcba: Pull complete d13bf203e905: Pull complete 4039240d2e0b: Pull complete Digest: sha256:35c4a2c15539c6c1e4e5fa4e554dac323ad0107d8eb5c582d6ff386b383b7dce Status: Downloaded newer image for ubuntu:latest root@54e7abca2706:/#
Look at the last line. The prompt changed to
root@54e7abca2706:/#. You are now in the running container as root. You can look around the file system. However, since Docker containers have such a stripped down, lightweight configuration, you will find that you will get a lot of “command not found” responses. Text editors like Nano or Vi are not installed, and basic networking commands like
ip a are also not available. Even
shutdown return a “command not found.”
# ping -c 4 google.com bash: ping: command not found
# vim /etc/hostname bash: vim: command not found
When you are done looking around type
exit to get out of the container.
So we have run our first container. You can get a list of all of your containers with this command:
$ docker ps a
The output displays in columns across the terminal screen. Here it is in a list:
CONTAINER ID: 54e7abca2706– A SHA-256 hash value that identifies the container.
IMAGE: ubuntu:latest– The image that the container comes form.
COMMAND: "bash"– The command invoked when the container was run.
CREATED: 2 minutes ago– When the container was created.
STATUS: Exited (0) 9 seconds ago– The container status.
PORTS:– Port-forwarding information (No value in this example.)
NAMES: quirky_matsumoto– A random word-pair name assigned by Docker.
CONTAINER ID and
NAMES values provide names that you can use to refer to the container.
IMAGE tells you the image where the container comes from. The
COMMAND value was set when we run the container.
STATUS tell us when the container was created and what it is doing right now.
PORTS displays port-forwarding information.
If you look at the
STATUS value, you see that the container was “Exited.” When you typed
exit, that stopped, or shut down, the container. Let’s delete the container with the
docker rm command (the docker command with the standard
rm, or remove, command). You can use the
CONTAINER ID or
NAMES values to identify the container. If you use
CONTAINER ID, you only need the first four or five characters of the hash value.
$ docker rm 54e7 $ docker rm quirky_matsumoto
When you enter either of those commands, the
CONTAINER ID or
NAMES value (whichever one you used, in this case the hash value) is returned in the output.
$ docker rm 54e7 54e7
You created and removed your first container. What about its image? Use this command to see all of your local images:
$ docker images
Again, the output displays horizontally across the terminal window, but it here it is in a list form:
REPOSITORY: ubuntu– Where the image comes from. In this case, Ubuntu shared it on the Docker Hub registry.
TAG: latest– The tag is often used as a version that corresponds with the image, or some other configuration information.
IMAGE ID: 74435f89ab78– Another SHA-256 hash used as an identifier.
CREATED: 6 days ago– When the image was posted to the registry.
SIZE: 73.9MB– The size of the image. The size value displayed for Docker images can be complicated. Images are made up of layers, and Docker shares layers between different images, so the sum of all image sizes is greater than the actual space on disk being occupied by images. You can read more about it on Docker’s website.
To delete an image, you use the command
docker rmi (for remove image), along with the
REPOSITORY:TAG pair or
IMAGE ID. As with a container, you don’t need the full hash value when using
IMAGE ID. The command and output looks like this:
$ docker rmi ubuntu Untagged: ubuntu:latest Untagged: ubuntu@sha256:35c4a2c15539c6c1e4e5fa4e554dac323ad0107d8eb5c582d6ff386b383b7dce Deleted: sha256:74435f89ab7825e19cf8c92c7b5c5ebd73ae2d0a2be16f49b3fb81c9062ab303 Deleted: sha256:8a8d1f0b34041a66f09e49bdc03e75c2190f606b0db7e08b75eb6747f7b49e11 Deleted: sha256:f1b8f74eff975ae600be0345aaac8f0a3d16680c2531ffc72f77c5e17cbfeeee Deleted: sha256:27d46ebb54384edbc8c807984f9eb065321912422b0e6c49d6a9cd8c8b7d8ffc Deleted: sha256:e1c75a5e0bfa094c407e411eb6cc8a159ee8b060cbd0398f1693978b4af9af10
(All of the
Deleted: sha256: hashes represent layers of an image being removed.)
Now let’s create a new container with two new options:
-rm: Remove. When you exit the container, it stops and is deleted. This is a useful demonstration of how ephemeral containers are, and helps you limit your list of containers.
-v: Volume. To provide persistent storage, the volume option links a path on the host computer to a path in the container. In this case
<host_path>represents where the directory is on your local machine. To the right of the colon, the
<container_path>value is the path to where you can access the host directory inside of the container.
$ docker run -rm -ti -v <host_path>:<container_path> ubuntu:latest bash
Here’s a specific example of how that looks:
$ docker run -rm -ti -v /Users/techwriter/Documents/docker:/host-directory ubuntu:latest bash
In this example,
docker run looks for the
ubuntu:latest image, and if it does not exist locally – which it doesn’t, because earlier you removed it with
docker rmi – it pulls it from the registry. If you want to keep a local copy of an image before running it as a container, you could download the image with
docker pull ubuntu:latest.
When the image is pulled and run as a container, you are in the container with a terminal, as root. If you list the contents of the top-level directory, the output displays the
host-directory that was created by the
-v option (bold and italics mine).
Other than the persistent storage that you created with the
-v option, this container will have the same configuration as the first container that you created. You can look around on the command line, but when you are finished and you type
exit to leave the container, it stops and is removed.
In the next article, you will use another Docker feature, Docker Compose, to create and orchestrate multiple containers so that you can run a WordPress site on your local machine: WordPress and Docker: Use Docker Compose.