On this post we will describe the basics of working with docker images, the building block of docker containers.
Basics of working with docker images
Listing Docker images
Let’s see what images are available to us on our Docker host. We can do this using the docker images command.
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 94e814e2efa8 5 weeks ago 88.9MB
The ubuntu image was downloaded from a repository. Images live inside repositories, and repositories live on registries. The default registry is the public registry managed by Docker, Inc., Docker Hub.
Inside Docker Hub (or on a Docker registry you run yourself), images are stored in repositories. You can think of an image repository as being much like a Git repository. It contains images, layers, and metadata about those images.
Each repository can contain multiple images (e.g., the ubuntu repository contains images for Ubuntu 12.04, 12.10, 13.04, 13.10, 14.04, 16.04). Let’s get another image from the ubuntu repository now.
# docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
34667c7e4631: Pull complete
d18d76a881a4: Pull complete
119c7358fbfc: Pull complete
2aaf13f3eff0: Pull complete
Digest: sha256:58d0da8bc2f434983c6ca4713b08be00ff5586eb5cdff47bcde4b2e88fd40f88
Status: Downloaded newer image for ubuntu:16.04
Let’s see what our docker images command reveals now.
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 9361ce633ff1 5 weeks ago 118MB
ubuntu latest 94e814e2efa8 5 weeks ago 88.9MB
You can see we’ve now got the latest Ubuntu image and the 16.04 image. This shows us that the ubuntu image is actually a series of images collected under a single repository.
We identify each image inside that repository by what Docker calls tags. Each image is being listed by the tags applied to it, so, for example, 12.04, 12.10, quantal, or precise and so on. Each tag marks together a series of image layers that represent a specific image (e.g., the 16.04 tag collects together all the layers of the Ubuntu 16.04 image). This allows us to store more than one image inside a repository.
We can refer to a specific image inside a repository by suffixing the repository name with a colon and a tag name, for example:
# docker run -i -t ubuntu:16.04 /bin/bash
root@0681604daef8:/#
This launches a container from the ubuntu:16.04 image, which is an Ubuntu 16.04 operating system.
It’s always a good idea to build a container from specific tags. That way we’ll know exactly what the source of our container is. There are differences, for example, between Ubuntu 14.04 and 16.04, so it would be useful to specifically state that we’re using ubuntu:16.04 so we know exactly what we’re getting.
There are two types of repositories: user repositories, which contain images contributed by Docker users, and top-level repositories, which are controlled by the people behind Docker.
Alternatively, a top-level repository only has a repository name like ubuntu. The top-level repositories are managed by Docker Inc and by selected vendors who provide curated base images that you can build upon (e.g., the Fedora team provides a fedora image). The top-level repositories also represent a commitment from vendors and Docker Inc that the images contained in them are well constructed, secure, and up to date.
Pulling images
When we run a container from images with the docker run command, if the image isn’t present locally already then Docker will download it from the Docker Hub.
By default, if you don’t specify a specific tag, Docker will download the latest tag.
Alternatively, we can use the docker pull command to pull images down ourselves preemptively. Using docker pull saves us some time launching a container from a new image. Let’s see that now by pulling down the fedora:21 base image.
# docker pull fedora:21
21: Pulling from library/fedora
fced6e4a4c06: Pull complete
Digest: sha256:a268e5e12257c7770eb44c24041baf5e728fba2eed1a84f007b81845ded0a485
Status: Downloaded newer image for fedora:21
Let’s see this new image on our Docker host using the docker images command.
This time, however, let’s narrow our review of the images to only the fedora images. To do so, we can specify the image name after the docker images command
# docker images fedora
REPOSITORY TAG IMAGE ID CREATED SIZE
fedora 21 ba6369d667d1 2 years ago 241MB
On the other hand if we want to see all the ubuntu images we can run
# docker images ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 9361ce633ff1 5 weeks ago 118MB
ubuntu latest 94e814e2efa8 5 weeks ago 88.9MB
Searching for images
We can also search all of the publicly available images on Docker Hub using the docker search command:
# docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 11270 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1583 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 708 [OK]
jrcs/letsencrypt-nginx-proxy-companion LetsEncrypt container to use with nginx as p… 504 [OK]
webdevops/php-nginx Nginx with PHP-FPM 125 [OK]
zabbix/zabbix-web-nginx-mysql Zabbix frontend based on Nginx web-server wi… 96 [OK]
bitnami/nginx Bitnami nginx Docker Image 65 [OK]
Here, we’ve searched the Docker Hub for the term puppet . It’ll search images and
return:
- Repository names
- Image descriptions
- Stars – these measure the popularity of an image
- Official – an image managed by the upstream developer (e.g., the fedora
- image managed by the Fedora team)
- Automated – an image built by the Docker Hub’s Automated Build process
Let’s pull down an image.
# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
27833a3ba0a5: Pull complete
ea005e36e544: Pull complete
d172c7f0578d: Pull complete
Digest: sha256:e71b1bf4281f25533cf15e6e5f9be4dac74d2328152edf7ecde23abc54e16c1c
Status: Downloaded newer image for nginx:latest
This will pull down the nginx image. We can then use this image to build a new container. Let’s do that now using the docker run command again. Let’s also specify we want the container to listen on port 80 (HTTP).
docker run --name mynginx1 -p 80:80 -d nginx
Lets get the IP address from within the nginx container running hostname -i:
# docker exec -i -t mynginx1 hostname -i
172.17.0.2
Now that we know the IP address and when we create the container we specified to open port 80, lets try to connect from the host:
# curl 172.17.0.2:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Great! we can see the default NGINX page, which confirms out NGINX container is Up and Running. That is all for now in regards to images, how to pull them and how to run containers based on these images.
On the next post we will describe how to create our own images.