Docker Lab 2 - Working with Ubuntu Images and Containers


Maintained by: mikerb@mit.edu         Get PDF


1  Overview and Objectives
2  Ubuntu Images
     2.1 Getting Ubuntu Images from Docker Hub
     2.2 Installing Packages and Confirming Release Info
     2.3 Obtaining a Larger Set of Utilities with One Install Command
3  Interacting with Ubuntu Containers
     3.1 Running and Exiting from Ubuntu Containers
     3.2 Running, Restarting and Reconnecting to a Ubuntu Container
     3.3 Running, Pausing, Unpausing a Ubuntu Container
4  Removing Images and Containers
     4.1 Simple Removing of Containers
     4.2 Automatically Removing a Container
     4.3 Removing a Running or Paused Container
     4.4 Removing an Image
     4.5 Removing an Image with Running Containers
     4.6 Remove all Containers
     4.7 Remove all Images
5  Revisiting Container State with Unbuntu Containers


1   Overview and Objectives


  • Goal - Obtain a Ubuntu image from Docker Hub
  • Goal -
  • Goal - Obtain your first Docker images
  • Goal - Start your first Docker containers
  • Goal - Become comfortable knowing the state of local images and containers

2   Ubuntu Images


Initially we focus on Ubuntu Linux images since our lab has been working with Ubuntu on physical machines for some years, and a couple of our motivating use cases are tied to Ubuntu. So in this short lab we will work with Ubuntu images and containers and gain familiarity with how to augment the initial containers, and create newly augmented images suitable for the work we have in mind.

2.1   Getting Ubuntu Images from Docker Hub    [top]


Ubuntu images for several releases may be obtained from Docker Hub:

    https://hub.docker.com/_/ubuntu/

This should bring you to a page that contains content similar to that shown below. Each of these entries represent a distinct image from a particular Ubuntu release. The terms on each line are tags that may be used with the ubuntu image name to get the desired release.

#fig_ubuntu tags

Figure 2.1: Ubuntu Image Tags: Various releases of Ubuntu are available with the corresponding tags.

For example, to get the Ubuntu 20.04 LTS image:

 $ docker pull ubuntu:20.04
 $ docker images
 REPOSITORY          TAG        IMAGE ID          CREATED          SIZE
 ubuntu              20.04      1d622ef86b13      3 weeks ago      73.9MB

Alternatively, to pull the image, and launch a container, with bash prompt, all on one command, the below command can be used.

 $ docker run -it ubuntu:20.04 bash
 root@3420dffd5c43:/# ls
 bin   dev  home  lib32  libx32  mnt  proc  run   srv  tmp  var
 boot  etc  lib   lib64  media   opt  root  sbin  sys  usr

Note the bash shell prompt is of the form "user@machine:pwd#". The container starts as the "root" user, and the machine name is the Container ID, "3420dffd5c43". The Container ID will be different on your system. The present working directory is "/".

There is not yet much that can be done with this container until further steps are taken to install packages or personal software. You can type exit at any time to stop the container and return to the shell prompt of your local file system. The container can be launched again by repeating the above docker run command. But any changes made prior to exiting the container will be lost, since the image has not changed, and each docker run will create a new container in exactly the same starting state. (Wrapping my head around this idea was an early challenge for me.)

2.2   Installing Packages and Confirming Release Info    [top]


Users accustomed to installing Ubuntu from scratch on a local computer, or virtual machine, may be surprised at how few utilities are installed on this container. This container is very thin, by design. The first time I launched a Ubuntu container like the above, the first thing I wanted to do was run the lsb_release command to verify the Ubuntu release information. Unfortunately, this utility was not installed, and needs to be installed first:

 root@3420dffd5c43:/# apt-get update
 ...
 Reading package lists... Done
 root@3420dffd5c43:/# apt-get install lsb-release

Note that first the apt-get update command needed to be run to update the internal list of packages available, since initially the list of packages is completely empty. Then the lsb_release utility was obtained from the lsb-release package. Now we can run lsb_release and verify that we are indeed working with the 20.04 release:

 root@3420dffd5c43:/# lsb_release -a 
 LSB Version:    core-11.1.0ubuntu2-noarch:security-11.1.0ubuntu2-noarch
 Distributor ID: Ubuntu
 Description:    Ubuntu 20.04 LTS
 Release:        20.04
 Codename:       focal

2.3   Obtaining a Larger Set of Utilities with One Install Command    [top]


Our plan is to continue to work with super thin Ubuntu images and containers, only installing what is needed.

But... it's worth noting that more familiar tool install configurations can be obtained easily using a meta-package [4]. The meta-package itself does not install anything. Instead, it is a link to several other packages that will be installed as dependencies. Here two useful options, the second one providing even more than the first:

 root@3420dffd5c43:/# apt-get update
 root@3420dffd5c43:/# apt-get -y install --no-install-recommends ubuntu-minimal
 or
 root@3420dffd5c43:/# apt-get -y install --no-install-recommends ubuntu-standard

Another useful meta-package is build-essential, [4]. This package includes five packages crucial to compiling software: g++, gcc, libc6-dev, make, dpkg-dev

 root@3420dffd5c43:/# apt-get update
 root@3420dffd5c43:/# apt-get -y install build-essential

Recall the -y argument to apt-get ensures that all user prompts for confirmation in the install process will take on the default values automatically. See [1] and [2] for more info on the Ubuntu packages.

3   Interacting with Ubuntu Containers


Once a Ubuntu image has been pulled to the local computer, containers can be run, paused, stopped, restarted, unpaused and so on. Furthermore, there are options for interacting with a running container. They are discussed here.

3.1   Running and Exiting from Ubuntu Containers    [top]


Let's start by running Ubuntu container as before:

 $ docker run -it ubuntu:20.04 bash
 root@3420dffd5c43:/#

What happens when we exit this container?

 root@3420dffd5c43:/# exit
 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 78312b579cf2    ubuntu:20.04    "bash"     4 mins ago    Exited (0) 2 sec ago   big_leavitt

The docker container ls -a command confirmed that the container has been exited, but it hasn't been removed.

What happens if these two steps are repeated?

 $ docker run -it ubuntu:20.04 bash
 root@3420dffd5c43:/# exit
 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     8 secs ago    Exited (0) 3 sec ago   hardcore_tesla
 78312b579cf2    ubuntu:20.04    "bash"     4 mins ago    Exited (0) 2 min ago   big_leavitt

The docker container ls -a command indicates that a new container was created, from the same image, and that both containers remain, and both have been exited.

3.2   Running, Restarting and Reconnecting to a Ubuntu Container    [top]


It is possible to restart and return to either of the above two containers:

 $ docker container restart a3c6bdc864f6
 a3c6bdc864f6 
 $ docker exec -it a3c6bdc864f6 bash
 root@a3c6bdc864f6:/#

First the container needs to be restarted. The docker container restart command above could have also been given the container name, hardcore_tesla, instead of the container ID. The exec command runs a new command in a running container [3].

In another terminal window you can see the change in container state:

 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     8 secs ago    Up 5 seconds           hardcore_tesla
 78312b579cf2    ubuntu:20.04    "bash"     4 mins ago    Exited (0) 2 min ago   big_leavitt

And finally, the restarted container may also be exited, or stopped, from outside the container. In the second (local) terminal window used above, try running the command:

 $ docker container stop a3c6bdc864f6
 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     2 mins ago    Exited (0) 5 sec ago   hardcore_tesla
 78312b579cf2    ubuntu:20.04    "bash"     4 mins ago    Exited (0) 2 min ago   big_leavitt

In the first terminal window, it can be noted that the container has exited, and the shell prompt is the local shell prompt. Exactly as if one had typed exit in the container window itself.

3.3   Running, Pausing, Unpausing a Ubuntu Container    [top]


It is possible to pause a running Ubuntu container rather than stopping it:

 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     18 mins ago   Up 15 minutes          hardcore_tesla
 $ docker container pause a3c6bdc864f6
 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     18 mins ago   Up 15 minutes (Paused) hardcore_tesla

If you had a bash session going in another terminal window with the now paused container, you will notice that the keyboard is non-responsive. The container can be un-paused with:

 $ docker container unpause a3c6bdc864f6
 $ docker container ls -a
 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     19 mins ago   Up 16 minutes          hardcore_tesla

Once the container is unpaused, any keystrokes that were typed in the terminal of the paused container will be immediately applied upon un-pause.

HINT: It is convenient to see the effects of starting, stopping, exiting containers etc, by re-running the "docker container ls -a" command. As a further convenience use a terminal window to auto-refresh this output as you're experimenting in other terminal windows, with the watch command:

 $ watch docker container ls -a
 Every 2.0s: docker container ls -a                         sausalito: Sat Jun 11 14:37:56 2022

 CONTAINER ID    IMAGE           COMMAND    CREATED       STATUS                 NAMES
 a3c6bdc864f6    ubuntu:20.04    "bash"     19 mins ago   Up 16 minutes          hardcore_tesla

This is similar to the top command in GNU/Linux. Just exit with ctrl-c.

4   Removing Images and Containers


So far in this lab we have explored how to:

  • Download (pull) Ubuntu images from Docker Hub to our local computer
  • Launch (run) a Ubuntu container from an image and have a bash session
  • Stop, restart and reconnect to a container
  • Pause and unpause a container

The last topic for the lab involves removing things. Personally I like to always know how to get back to my starting state. After this discussion you should feel confident that you can create as many images and containers as you like, experiment freely with them, and easily get back to a clean starting state.

As before, we will work with Ubuntu images and containers. We will exlore:

  • How to remove images and containers from our local computer
  • What happens when we try to remove a running container
  • What happens when we try to remove an image related to a running container
  • How to remove all containers with a single command
  • How to remove all images with a single command

4.1   Simple Removing of Containers    [top]


A straight-forward example of removing a container is below. A new container is created with a bash session.

 $ docker run -it ubuntu:20.04 bash
 root@3420dffd5c43:/#

In a second terminal window this container can be seen with docker container ls:

 $ docker container ls
 CONTAINER ID     IMAGE            COMMAND    CREATED        STATUS      NAMES
 4c548ea0fdc2     ubuntu:20.04     "bash"     3 secs ago     Up 2 secs   sad_jane

Back in the first terminal, we exit, and note that it is still listed, but its status is Exited, and we have to use the -a argument in docker container ls -a to see this container listed:

 root@3420dffd5c43:/# exit
 $ docker container ls
 CONTAINER ID     IMAGE            COMMAND    CREATED        STATUS                   NAMES
 $ docker container ls -a 
 CONTAINER ID     IMAGE            COMMAND    CREATED        STATUS                   NAMES
 4c548ea0fdc2     ubuntu:20.04     "bash"     3 mins ago     Exited (0) 2 secs agoe   sad_jane

The container has not been removed. If we wanted, this container could still be restarted and reconnected to a new bash session. But we'll remove it instead. To remove the container:

 $ docker container rm 4c548ea0fdc2 
 4c548ea0fdc2 
 $ docker container ls -a 
 CONTAINER ID     IMAGE            COMMAND    CREATED        STATUS                   NAMES

4.2   Automatically Removing a Container    [top]


An even simpler way to remove a container is to arrange to have it removed automatically as soon as the container is stopped (exited). To do this, just include the --rm argument when the container is launched (started):

 $ docker run --rm -it ubuntu:20.04 bash
 root@3420dffd5c43:/# exit
 $ docker container ls -a
 CONTAINER ID     IMAGE            COMMAND    CREATED        STATUS                   NAMES

4.3   Removing a Running or Paused Container    [top]


Normally the action to remove a container should be taken only on a container that has been stopped. Let's see what happens when we try to remove a container that is still running. In the first terminal:

 $ docker run -it ubuntu:20.04 bash
 root@e538ef4d8e9e:/# 

In a second terminal window, try to remove the container:

 $ docker rm e538ef4d8e9e
 Error response from daemon: You cannot remove a running container
 e538ef4d8e9e6c0d0e242647a0e234ad0886862b192f40c3752b97b23b0bf186. Stop the
 container before attempting removal or force remove

The removal will not carried out. Note the full UUID for the container in the error message. Recall the shortened container ID, e538ef4d8e9e, is just the first 12 characters of the longer 64 character UUID.

As the error message indicates, the removal can be forced, and this is done with:

 $ docker rm --force e538ef4d8e9e
 e538ef4d8e9e

The same situation applies if the container were paused instead of running. As a general practice, we will try to avoid using --force in any of our attempts to remove a container by ensuring they are stopped (exited) first.

4.4   Removing an Image    [top]


Removing an image is straight-forward when there are no containers running created from that image. In the case above, for example, a Ubuntu container was created:

 $ docker run -it ubuntu:20.04 bash
 root@8df9aee15e5b:/# 

In a second terminal window, the container can be seen, and the image that created it:

 $ docker containers ls
 CONTAINER ID        IMAGE          COMMAND    CREATED          STATUS         NAMES
 8df9aee15e5b        ubuntu:20.04   "bash"     12 secs ago      Up 12 secs     quirky_joe
 $ docker images
 REPOSITORY          TAG            IMAGE ID         CREATED          SIZE
 ubuntu              20.04          1d622ef86b13     4 hours ago      73.9MB

Removing the image is straight-forward with the docker container rm command, providing it either the Image ID or the Image name. First the container is stopped and removed:

 $ docker container stop 8df9aee15e5b
 8df9aee15e5b
 $ docker container rm 8df9aee15e5b
 8df9aee15e5b
 $ docker image rm 1d622ef86b13
 1d622ef86b13
 $ docker images
 REPOSITORY          TAG            IMAGE ID         CREATED          SIZE

4.5   Removing an Image with Running Containers    [top]


An image cannot be removed if there are any containers attached to it, whether the container is running, paused, or stopped. If you'd like to try, you will see something like this:

 $ docker rmi 1d622ef86b13
 Error response from daemon: conflict: unable to delete 1d622ef86b13 (cannot be forced) - image 
 is being used by running container 9b3db02a3e3d

Just remove the container first.

4.6   Remove all Containers    [top]


To remove all containers (running, paused or stopped), the below command can be used. It uses the output of the docker ps -aq command which just returns the list of Docker container IDs:

 $ docker ps -aq
 9b3db02a3e3d
 50a674ab9d1e
 f868dea6b7a0

The output of the above command is then used as input in the below one-liner to remove all containers.

 $ docker rm -f $(docker ps -aq)

The -f argument of course will force remove all containers, even if they are still running or paused.

FYI, a bit trickier command below can be used to remove all containers (running, paused or stopped) based on a Docker image name. The below will remove all containers attached to the image "ubuntu:20.4":

 # docker ps -a | awk '{ print $1,$2 }' | grep ubuntu:20.04 | awk '{print $1 }' | xargs -I {} docker rm {}

4.7   Remove all Images    [top]


5   Revisiting Container State with Unbuntu Containers


There are at least five distinct states associated with containers:

  • Created: A created container is one that has been initialized with the docker create command but hasn’t been started yet.
  • Running:
  • Paused:
  • Stopped/Exited: The exited status is commonly referred to as stopped and indicates there are no running processes inside the container (this is also true of a created container, but an exited container will have already been started at least once). A container exits when its main processes exits. An exited container can be restarted with the docker start command. A stopped container is not the same as an image. A stopped container will retain changes to its settings, metadata, and filesystem, including runtime configuration such as IP address that are not stored in images. The restarting state is rarely seen in practice and occurs when the Docker engine attempts to restart a failed container, [.
  • Dead:

    \Large

    URL References

[1] https://packages.ubuntu.com/bionic/ubuntu-minimal

[2] https://packages.ubuntu.com/bionic/ubuntu-standard

[3] https://docs.docker.com/engine/reference/commandline/exec/

[4] https://pimylifeup.com/ubuntu-build-essential/


Page built from LaTeX source using texwiki, developed at MIT. Errata to issues@moos-ivp.org. Get PDF