Introduction
In this lab, we will explore Docker images, which are the foundation for creating and running containers. We will learn how to pull images from Docker Hub, run containers using different image versions, list and remove images, understand image layers, search for images, and perform basic image tagging. This hands-on experience will provide you with essential skills for working with Docker images effectively. Don't worry if you're new to Docker - we'll guide you through each step with detailed explanations.
Pulling Images from Docker Hub
Docker Hub is a public repository of Docker images, similar to GitHub for code. It's where you can find pre-built images for many popular software applications and operating systems. Let's start by pulling (downloading) the official Nginx image.
Open a terminal on your system. You should see a prompt that looks something like this:
labex:project/ $
Now, let's pull the Nginx image. Type the following command and press Enter:
docker pull nginx
This command tells Docker to download the latest version of the Nginx image from Docker Hub. You should see output similar to this:
Using default tag: latest
latest: Pulling from library/nginx
5040bd298390: Pull complete
d7a91cdb22f0: Pull complete
9cac4850e5df: Pull complete
Digest: sha256:33ff28a2763feccc1e1071a97960b7fef714d6e17e2d0ff573b74825d0049303
Status: Downloaded newer image for nginx:latest
Let's break down what's happening here:
- "Using default tag: latest" - When you don't specify a version, Docker assumes you want the latest version.
- The next few lines show Docker downloading different "layers" of the image. Each layer represents a set of filesystem changes.
- The "Digest" is a unique identifier for this exact version of the image.
- The last line confirms that the image has been successfully downloaded.
Now that we've downloaded the image, let's verify that it's on our system. We can do this by listing all the images Docker has locally:
docker images
You should see output similar to this:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 141MB
This tells us:
- REPOSITORY: The name of the image (nginx)
- TAG: The version of the image (latest)
- IMAGE ID: A unique identifier for this image
- CREATED: When this version of the image was created
- SIZE: How much disk space the image takes up
Don't worry if the exact numbers are different - the important thing is that you see an entry for nginx.
If you're curious about what other images are on your system, you might see entries for "jenkins/jenkins" and "gcr.io/k8s-minikube/kicbase". These are pre-installed images that we won't be using in this lab.
Running Different Versions of an Image
Docker allows you to run specific versions of an image by using tags. Tags are like aliases for specific versions of an image. Let's explore this concept with the Python image.
First, let's pull the latest Python image:
docker pull python
You'll see similar output to when we pulled the Nginx image. This is downloading the latest version of Python.
Now, let's pull a specific version of Python, say version 3.7:
docker pull python:3.7
Notice how we added :3.7
after python
. This tells Docker to pull version 3.7 specifically, rather than the latest version.
Let's list our Python images to see the different versions:
docker images python
You should see output similar to this:
REPOSITORY TAG IMAGE ID CREATED SIZE
python 3.7 1f1a7b570fbd 2 weeks ago 907MB
python latest 98ccd1643c71 2 weeks ago 920MB
Now we have two Python images: one tagged latest
(which is actually Python 3.9 or 3.10, depending on when you're doing this lab), and one tagged 3.7
.
Let's run containers using these different versions to see the difference:
docker run --rm python:latest python --version
This command does a few things:
-
docker run
creates and starts a new container -
--rm
tells Docker to remove the container after it exits -
python:latest
specifies which image to use -
python --version
is the command to run inside the container
You should see the latest Python version in the output.
Now let's do the same with Python 3.7:
docker run python:3.7 python --version
This time, you should see Python 3.7.x
in the output, where x
is the latest patch version of Python 3.7.
These commands demonstrate how you can use different versions of the same software by using different image tags. This is incredibly useful when you need to run applications that require specific versions of Python (or any other software).
Listing and Removing Images
As you work with Docker, you'll accumulate images over time. It's important to know how to manage these images, including how to list them and remove ones you no longer need.
Let's start by listing all the images on your system:
docker images
You should see a list of all the images you've pulled so far, including Nginx and the Python images.
Now, let's say we want to remove the Python 3.7 image to free up some space. We can do this using the docker rmi
command (rmi stands for "remove image"):
docker rmi python:3.7
If this command succeeds, you'll see output like this:
Untagged: python:3.7
Untagged: python@sha256:1f93c63...
Deleted: sha256:1f1a7b57...
Deleted: sha256:8c75ecde...
...
However, you might instead see an error message like this:
Error response from daemon: conflict: unable to remove repository reference "python:3.7" (must force) - container <container_id> is using its referenced image <image_id>
This error occurs if there's a container (running or stopped) that was created from this image. Docker prevents you from removing images that are in use to maintain system integrity.
To resolve this, we need to remove any containers using this image first. Let's list all containers (including stopped ones):
docker ps -a
Look for any containers that were created from the python:3.7
image. If you find any, remove them using the docker rm
command:
docker rm <container_id>
Replace <container_id>
with the actual ID of the container you want to remove.
Now try removing the image again:
docker rmi python:3.7
This time it should succeed.
Let's verify that the image has been removed by listing Python images again:
docker images python
You should no longer see the Python 3.7 image in the list.
Understanding Image Layers
Docker images are built using a layered filesystem. Each layer represents a set of filesystem changes. This layered approach allows Docker to be efficient with storage and network usage. Let's explore this concept.
First, let's inspect the layers of the Nginx image we pulled earlier:
docker inspect --format='{{.RootFS.Layers}}' nginx
You'll see output similar to this:
[sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8 sha256:b5357ce95c68acd9c9672ec76e3b2a2ff3f8f62a2bcc1866b8811572f4d409af]
Each of these long strings (called SHA256 hashes) represents a layer in the image. Each layer corresponds to a command in the Dockerfile used to build the image.
To better understand layers, let's create a simple custom image. First, create a new file named Dockerfile
in your current directory:
nano Dockerfile
In this file, add the following content:
FROM nginx
RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html
This Dockerfile does two things:
- It starts with the Nginx image we pulled earlier (
FROM nginx
) - It adds a new file to the image (
RUN echo...
)
Save and exit the file (in nano, you can do this by pressing Ctrl+X, then Y, then Enter).
Now let's build this image:
docker build -t custom-nginx .
Sample output:
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 5ef79149e0ec
Step 2/2 : RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html
---> Running in 2fa43e649234
Removing intermediate container 2fa43e649234
---> 73b62663b5c3
Successfully built 73b62663b5c3
Successfully tagged custom-nginx:latest
This command builds a new image based on our Dockerfile and tags it as custom-nginx
. The .
at the end tells Docker to look for the Dockerfile in the current directory.
Now, let's inspect the layers of our custom image:
docker inspect --format='{{.RootFS.Layers}}' custom-nginx
You'll notice that this image has one more layer than the original Nginx image. This additional layer represents the changes made by our RUN
command.
Understanding layers is crucial because:
- Layers are cached, speeding up builds of similar images
- Layers are shared between images, saving disk space
- When pushing or pulling images, only changed layers need to be transferred
Searching for Images on Docker Hub
Docker Hub hosts a vast collection of images. While you can search for images on the Docker Hub website, Docker also provides a command-line tool to search for images directly from your terminal.
Let's start by searching for Nginx images:
docker search nginx
This will return a list of images related to Nginx. The output includes several columns:
- NAME: The name of the image
- DESCRIPTION: A brief description of the image
- STARS: The number of stars the image has on Docker Hub (indicating popularity)
- OFFICIAL: Whether this is an official image maintained by Docker
- AUTOMATED: Whether this image is automatically built from a GitHub repository
For example, you might see something like this:
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 15763 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker c... 2088 [OK]
...
The official Nginx image is typically at the top of this list.
Now, let's try searching for a specific version of Python:
docker search python:3.8
You'll notice that this search doesn't work quite as you might expect. Docker search doesn't support searching for specific tags (like 3.8). Instead, it will search for images with "python:3.8" in their name or description.
To find specific versions of an image, it's often better to:
- Search for the general image name (e.g.,
docker search python
) - Visit the Docker Hub website for more detailed information
- Use
docker pull
to download the image and then inspect it locally
Remember, docker search
is a quick way to find images, but for more detailed information, the Docker Hub website is often more useful.
Saving and Loading Images
Docker allows you to save images as tar files and load them later. This is useful for transferring images between systems without using a registry, or for backing up images.
Let's start by saving the Nginx image to a file:
docker save nginx > nginx.tar
This command saves the Nginx image to a file named nginx.tar
in your current directory. The >
symbol is used to redirect the output of the docker save
command to a file.
You can verify that the file was created by listing the contents of your current directory:
ls -lh nginx.tar
You should see the nginx.tar
file listed, along with its size (which should be over 100MB).
Now, let's remove the Nginx image from our system to simulate transferring the image to a system that doesn't have it:
docker rmi nginx
Verify that the image is gone:
docker images nginx
You should see no results, indicating that the Nginx image has been removed from your system.
Now, let's load the image back from the tar file:
docker load < nginx.tar
The <
symbol is used to redirect the contents of the nginx.tar
file as input to the docker load
command.
After the load completes, verify that the Nginx image is back:
docker images nginx
You should see the Nginx image in the list again, just as it was before we removed it.
This process of saving and loading images can be very useful when you need to:
- Transfer images to a system without internet access
- Back up specific versions of images
- Share custom images with others without using a registry
Image Tagging Basics
Tagging is a way to create aliases for your Docker images. It's commonly used for versioning and organizing images. Let's explore how to tag images.
First, let's create a new tag for our Nginx image:
docker tag nginx:latest my-nginx:v1
This command creates a new tag my-nginx:v1
that points to the same image as nginx:latest
. Here's what each part means:
-
nginx:latest
is the source image and tag -
my-nginx
is the new image name we're creating -
v1
is the new tag we're assigning
Now, list your images to see the new tag:
docker images
You should see both nginx:latest
and my-nginx:v1
in the list. Notice that they have the same Image ID - this is because they're actually the same image, just with different names.
You can use this new tag to run a container:
docker run -d --name my-nginx-container my-nginx:v1
This command does the following:
-
-d
runs the container in detached mode (in the background) -
--name my-nginx-container
gives a name to our new container -
my-nginx:v1
is the image and tag we're using to create the container
Verify that the container is running:
docker ps
You should see your container in the list of running containers.
Tagging is useful for several reasons:
- Version control: You can tag images with version numbers (v1, v2, etc.)
- Environment separation: You might tag images for different environments (dev, staging, prod)
- Readability: Custom tags can make it clearer what an image is for
Remember, tags are just aliases - they don't create new images, they just create new names that point to existing images.
Summary
In this lab, we explored various aspects of working with Docker images. We learned how to:
- Pull images from Docker Hub
- Run containers using different image versions
- List and remove images
- Understand image layers
- Search for images on Docker Hub
- Save and load images
- Perform basic image tagging
These skills form the foundation for effectively managing Docker images in your projects. As you continue your Docker journey, you'll find these operations essential for building and deploying containerized applications.
Remember, Docker images are at the core of how Docker operates. They provide a consistent, portable, and efficient way to package and distribute applications. By mastering these image operations, you're well on your way to becoming proficient with Docker.
Keep practicing these commands and exploring different images. The more you work with Docker, the more comfortable and proficient you'll become. Happy Dockering!
🚀 Practice Now: Working with Docker Images
Want to Learn More?
- 🌳 Learn the latest Linux Skill Trees
- 📖 Read More Linux Tutorials
- 💬 Join our Discord or tweet us @WeAreLabEx
Top comments (0)