Now that we have covered the basic history and technology of containers, we want leverage some of those concepts in this lab. First we need to understand the concept of Docker Hub.
Docker Hub is the repository in which Docker users can create, test, store and distribute container images amongst each other. Docker Hub can be leveraged in the cloud, but many companies host their own local Docker Hub repository.
Click Docker Hub in a browser window. In the top portion of the window is the search bar. Enter ubuntu. In the search results you will find a result like this:
When you click on details you will get a description page that covers various information points and examples of the Docker container. On the top right you will see a window with the docker pull command (We will explain this soon).
One of the key concepts to understand is the concept of tags. For example, in the case of ubuntu it can be called in various ways. In the top of the page there is a tab called Tags.
If you click on this you will see a list. These tag names can be invoked individually to request a more specific version of the container. These are used in many ways. In the description section it stipulates that for ubuntu:
As best practice it isn't recommended to just pull a container without a tag. As in this case you are gambling as to what release exactly your application will be using as a base operating system. And that in itself could lead to failures if changes happen in the cloud. To avoid this condition it is recommended to always be specific. Let's look at the ubuntu 16.04 as an example. The release name is xenial.
As you can see, there are various releases. Users always want to make sure they select the right build for their project. The idea behind this verification is to make sure the user has the correct version of the container. This comes into play because a user may need a specific version of the container.
Let's now pull a specific version of ubuntu to play with. We just want to pull the latest 16.04 release container.
docker pull ubuntu:16.04
You should see an output as follows:
16.04: Pulling from library/ubuntu 22dc81ace0ea: Pull complete 1a8b3c87dba3: Pull complete 91390a1c435a: Pull complete 07844b14977e: Pull complete b78396653dae: Pull complete Digest: sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6 Status: Downloaded newer image for ubuntu:16.04
To see the downloaded container in your local file store, issue the following command:
[root@pod09-master ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu 16.04 f975c5035748 10 days ago 124MB
For every Docker image you download, the Docker client will tag it with an image id. This is what you will have to use to manipulate that image.
As we discussed containers can be hosted in either cloud or private locations. Many people simply use a container from one of the public container registries like Docker Hub. The error many people make is to start with containers that are based on known distributions. These can lead to fat containers that are a drag on your plans for a streamlined private cloud.
There are a variety of stripped down linux distribution containers that have a bare minimum install. One of these distributions is Alpine Linux. The smallest available Alpine Linux distribution starts at a couple of megabytes in size.
When you downloaded the Ubuntu image before, it had output similar to the following:
16.04: Pulling from library/ubuntu 0a01a72a686c: Pull complete cc899a5544da: Pull complete 19197c550755: Pull complete 716d454e56b6: Pull complete Digest: sha256:3f3ee50cb89bc12028bab7d1e187ae57f12b957135b91648702e835c37c6c971 Status: Downloaded newer image for ubuntu:16.04 docker.io/library/ubuntu:16.04
Each of the lines that end with
Pull Complete are layers of the container that you
docker history command provides the details of what each of these various
layers consist of. To get this first issue the command
The output contains the images that have been downloaded, one that you pulled and one that
was downloaded when you issued the
docker run command.
[root@pod09-master ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 96da9143fb18 10 days ago 124MB
Copy the docker image ID from the downloaded ubuntu image and then use this ID for the
docker history command. Below is the sample to follow:
[root@pod09-master ~]# docker history 96da9143fb18 IMAGE CREATED CREATED BY SIZE COMMENT 96da9143fb18 10 days ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 10 days ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B <missing> 10 days ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B <missing> 10 days ago /bin/sh -c rm -rf /var/lib/apt/lists/* 0B <missing> 10 days ago /bin/sh -c #(nop) ADD file:4b2eb5cd0b37ca015… 124MB
The important reason to understand this step is because it gives you an idea on the efficiency of the container in a host. If your application needs hundreds of containers that are based on the same image, then only the difference of that R/W layer created when the container was built counts towards the incremental storage on the compute resource.
In this example, the base image is 112MB in size. The three combined containers that are depicted in the diagram would mean that the three containers in this host are consuming a total of 220MB (112 + 87 + 9 + 12 ).
If these were micro-services utilizing virtual machines then at best you would start with 112MB * 3 plus (87 + 9 + 12 ) or 444MB. If you consider a hefty compute resource that could run hundreds of containers, you can start to understand the advantage of containerized micro-services.
The first exercise you will do is to start a very small alpine container from docker hub.
docker run -d -t -i --rm -h=ubuntu-ciscolive --name ubuntu-ciscolive ubuntu:16.04
To explain we have provided these parameters:
Allocate a pseudo tty. If you don't allocate a pseudo tty then when the container principal process starts ( bash ) it would not have a way to get input and fails causing the container to stop.
This provides the hostname for the container
Upon termination of process or stopping of container, delete the container.
Provide a name to be able to manage container without having to use the identifier.
After running this command you will be returned to your prompt. Now you can see the container that is running.
docker ps -a
The output should be similar to the following with different container ID.
[root@pod09-master ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 62ef904844b6 ubuntu:16.04 "/bin/bash" 7 seconds ago Up 6 seconds ubuntu-ciscolive
Now that you have a working container you can attach to the container itself.
docker attach ubuntu-ciscolive
Once inside the container execute the command
ps -ef. You should only see
two processes. The
ps process and the actual
root@ubuntu-ciscolive:/# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 13:50 pts/0 00:00:00 /bin/bash root 9 1 0 14:00 pts/0 00:00:00 ps -ef
Now exit the container.
At this point the container will be exited and removed ( deleted ) from the system because of the --rm parameter. As a reference, you can exit an active detached container easily without stopping the container with the sequence CTRL + p and CTRL + q. In the previous set using the exit command kills the bash shell causing the container to terminate.
You can verify that the container has been deleted, by executing the
docker ps -a command as previously shown.