How to search, pull, list and run a docker container

Containers enable you to package an application with all the components it needs, such as libraries and other dependencies and ship it as one package. Docker containers have revolutionized the software supply chain in both small and large enterprises. In this post, we will exercise all of the basic Docker functionality to search, retrieve, and use Docker images.

1. Search Docker images from the Docker Hub

Docker images can be searched in much the same way you search any collection. Run the following command to learn about one of the images that we will be using in this lab:

$ docker search fedora/apache

You should see something like this:

$ docker search fedora/apache
NAME             DESCRIPTION    STARS     OFFICIAL   AUTOMATED
fedora/apache                    26                   [OK]
fedora/systemd-apache            5                    [OK]
...

The first part of the name is the namespace (in this case Fedora project) and the second part is the package, which usually is descriptive of the OS or the image’s purpose. As for the other fields:

  • Stars: Docker images can be rated by users, the more stars a container has, the more popular it is.
  • **Official: **The folks at Docker maintain a number of “official” images, as denoted by this field.
  • Automated: Docker supports automated builds; any images that are produced by the automated build process are flagged with this.

2. Pull a Docker Image from the Docker Hub

Docker images are actually comprised of layered file systems. When you perform a docker pull, you initiate the parallel download of all of the file system components that make up your requested Docker image. Try it now by running the following:

$ docker pull fedora/apache:latest

When it is done, you should see output similar to this:

$ docker pull fedora/apache:latest
 Pulling repository fedora/apache
 2e11d8fd18b3: Download complete
 511136ea3c5a: Download complete
 ff75b0852d47: Download complete
 0dae8c30a0b2: Download complete
 84f33df93401: Download complete
 24b116bb2956: Download complete
 a7f290a6f21d: Download complete
 eb86e2be11d4: Download complete
 c06d2cba0d4a: Download complete
 f0b140ef8cdd: Download complete
 b05601b61180: Download complete

In the case of this particular Docker image, each of these filesystems represents a different tagged version of the image. Most Docker images are composed of multiple filesystem layers.

3. List Downloaded Images

This command shows you all of your locally available Docker images:

$ docker images

You should see something like this:

$ docker images
REPOSITORY       TAG      IMAGE ID      CREATED   VIRTUAL SIZE
 fedora/apache   latest  2e11d8fd18b3    9 days ago      554.1 MB
 ....

Since we pre-installed other Docker images on the EC2 machine you will see all the other images on your machine as well.

4. Running a Container

To start this exercise, first familiarize yourself with docker ps:

$ docker ps
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

Nothing is running right now, so the list is empty. Now kick off a simple container with docker run:

$ docker run -i -t fedora/apache /bin/echo 'hello world'
hello world

Here’s a breakdown of what just happened:

  • -i: Make an interactive connection to the container by grabbing STDIN
  • -t: Assign a pseudo-terminal in the container
  • fedora/apache: the image to run as a container
  • /bin/echo ‘hello world’: A command passed to the container’s pseudo terminal via STDIN

Notice that we still haven’t explicitly identified which tagged version of the image we want to run. In this situation, Docker defaults to using the version tagged with latest. Now run docker ps again:

$ docker ps
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

Still nothing! This is because the Docker container that we ran isn’t running anymore. It stopped as soon as its primary process exited. Try running docker ps with the -l argument to see the result of the last container invocation:

$ docker ps -l
CONTAINER ID        IMAGE                  COMMAND                CREATED              STATUS                          PORTS               NAMES
5e05cd28f29c        fedora/apache:latest   /bin/echo 'hello wor   About a minute ago   Exited (0) About a minute ago                       silly_kowalevski

Notice that docker assigned a random id and name to our container when it spun it up. We will revist the name piece later in the exercises.

5. Running a container as a “daemon”

While having an image spin up and run command is “neat”, now it’s time to do some more useful tasks. Let’s get our image to start up and serve HTML content through Apache Web Server. Enter the following command:

$ docker run -d -P fedora/apache 798a3749cd7e0721a59af2879ecfebfd1096cb1c925ab73549102c06b788a4e5

Here is a breakdown of the flags:

  • -d means run the container in the background ( which means don’t run and exit)
  • -P means map any required network ports inside our container to ports on the host (basically automatically do port-mapping)

If you remember back to when you did the docker history command, one of the changes was to have the image spin up Apache when it is spun up as a container. The end result is that by running the command above we now have Apache running and serving up index.html. Now let’s find out what port we should use to get to Apache. Time to use the trusty docker ps command:

$ docker ps
CONTAINER ID        IMAGE                  COMMAND          CREATED             STATUS              PORTS                       NAMES
798a3749cd7e        fedora/apache:latest   /run-apache.sh   5 seconds ago       Up 5 seconds        0.0.0.0:49153->80/tcp    elegant_pare

docker ps shows something even without the -l because we used the -d flag when calling docker run. What is also different is you can see that there is an entry for ports:

0.0.0.0:49153->80/tcp

This line indicates that port 49153 on the host machine points to port 80 on the container. It also is only exposing TCP traffic. Based on this we can execute the following command on our host machine:

$ curl -v 0.0.0.0:49153
* About to connect() to 0.0.0.0 port 49153 (#0)
*   Trying 0.0.0.0... connected
* Connected to 0.0.0.0 (0.0.0.0) port 49153 (#0)
 > GET / HTTP/1.1
 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu)
 libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3  libidn/1.18 libssh2/1.4.2
 > Host: 0.0.0.0:49153
 > Accept: */*
 >
 < HTTP/1.1 200 OK
 < Date: Thu, 09 Oct 2014 18:35:13 GMT
 < Server: Apache/2.4.10 (Fedora)
 < Last-Modified: Mon, 29 Sep 2014 12:28:50 GMT
 < ETag: "7-5043368b3a480"
 < Accept-Ranges: bytes
 < Content-Length: 7
 < Content-Type: text/html; charset=UTF-8
 <
 Apache
 * Connection #0 to host 0.0.0.0 left intact
 * Closing connection #0

Voila, you have successfully spun up a Docker image and have it serving content. If you want to stop this Docker image from running just enter:

$ docker kill elegant_pare

You could have also used the container ID in place of the name. Time for us to start modifying Docker images.