What are Docker Images?

Docker Images are read-only templates comprised of multiple layers which act as a blueprint of the container environment. Docker Images are built by specifying instructions inside a special file called Dockerfile. Dockerfile allows us to define instructions to create a customized container environment. We can execute the Docker build command on a Dockerfile to create a Docker Image. This Docker image can then be used to create one or more instances of Docker containers associated with that image.

Introduction to Docker Images

As discussed above, Docker Images are built using multiple file layers that are all read-only. Each instruction that we specify inside a Dockerfile creates a separate image layer on top of the previous ones. The image layers contains all the code, libraries, dependencies, binaries, and configuration files that are specific to the container environment that we want to create for our application.

You might be thinking that since Docker Images are immutable, then how can we make changes to them? There are two ways to do so. The first one is by making changes directly to the Dockerfile and rebuild the image once again. This might prove to be costly especially when images are of large sizes. The second and better way to do so is by creating containers associated with that image. We can then make the changes inside the container environment and commit them to create a new version of the image.

How do Docker Images work?

Docker Image Layers
Docker Image Layers

We have earlier mentioned that Docker Images contains multiple read-only layers. In the above image, you can see an overview of the same. We have an Ubuntu image which can be directly pulled from any Docker registry such as Dockerhub. The bottom-most layer is the base image layer. As we keep on adding Dockerfile instructions on top of the base image, each instruction will add a new layer. All these layers are read-only. Once we have finished the Dockerfile and executed the Docker build command, we will get our final image.

This image is also read-only. In order to make changes to this image, we can go back and change the instructions that we have included in the Dockerfile to create this image. Or we can create a container associated with this image using the Docker run command. Once we have access to the container’s environment, we can perform the changes inside it and commit the changes using the Docker commit command. This will create a new version of the image.

How can we pull images from Dockerhub?

Dockerhub is Docker’s offical registry. There are tons of official and vendor-specific pre-built images in Dockerhub. Some important ones include Ubuntu, Python, CentOs, Nginx, Apache, Java, NodeJs, etc.

We can leverage Dockerhub to directly pull these images from it using the Docker pull command. To do so, we need to create an account in Dockerhub first. Next, using the login credential, we need to sign in to Dockerhub through the command-line in our host machine. We can do so by executing the Docker login command.

Once we have successfully logged in to Dockerhub, we can create our own private repository in Dockerhub and push our own customized Docker images there. This will allow us to share our images with our team members. We can create both private and public repositories there. We can also directly pull images such as ubuntu, python, and several other images using the Docker pull command. There are 2 ways in which we can use these images.

  1. We can use these images directly by creating a container using the Docker run command. Once we have access to the container environment, we can execute commands inside it easily. If we stop the container directly, all our changes will be lost. If we want our changes to persist the next time we run it, we need to commit these changes using the Docker commit command.
  2. We can also use these images as a base image by specifying FROM <image-name> instruction in our Dockerfile. On top this instruction, we can specify other instructions such as RUN to install packages, CMD to run an application, etc. Finally, we can use the Docker build command to build the image. Then, we can run a container using the Docker run command.

Let’s try to pull an Ubuntu image directly from Dockerhub. The syntax of the Docker pull command is –

$  docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Docker Pull Command in Docker Images
Docker Pull Command

How to build Docker Images using Dockerfile?

Another way to create a Docker Image is by specifying instructions inside a Dockerfile. Let’s see how to do so. Create a file called Dockerfile without any extension inside a folder. Also, create an empty file called techtutorialsite.txt.

FROM ubuntu:latest
WORKDIR /app
COPY . .
RUN echo "Welcome to techtutorialsite" > techtutorialsite.txt
CMD ["cat", "techtutorialsite.txt"]

Both the files must exist in the same folder. In the above Dockerfile, let’s understand the instructions one by one.

  1. We have used the FROM instruction to pull an Ubuntu base image with the latest tag directly from Dockerhub. If we don’t specify any tag, it will automatically use the latest tag to pull the latest version of the image. Other tags include 20.04, 18.04, etc.
  2. Next, we have used the WORKDIR instruction to specify the default working directory of the container. If such a directory does not exist inside the container, a new one will be automatically created. All the subsequent instructions will be executed inside this directory until a new WORKDIR instruction is encountered.
  3. We have used the COPY instruction to copy the files inside the current directory (mentioned using a dot) in our host machine to the default working directory in the container. The files include both the techtutorialsite.txt and Dockerfile.
  4. Next, we have used the RUN instruction to specify a command that needs to be run inside the container. We have used the echo command to insert text inside the file.
  5. Finally, we have used CMD instruction to specify a command that needs to be run as soon as the container is created. We have used the cat command to print the contents of the file.

Let’s use the Docker build command to build this image. The syntax is –

$ docker build [OPTIONS] PATH | URL | -
Docker Build Command
Docker Build Command

In the above output, you can see how the Docker daemon executes each instruction inside the Dockerfile step by step. Also, after each instruction execution, you can see the image ID of the new image layer that is created. The -t (tag) option is used to specify a tag to the image. In this case, we have not mentioned any tag. Hence, the daemon will automatically assign the latest tag. Also, the dot at the end specifies the path of the Dockerfile.

When we pull images or create images from Dockerfile, the Docker daemon first checks for an existing image in the local machine by comparing the image digest. If it finds any match, then a new image is not pulled. If not, then the image with the specific tag is pulled and used.

How to List Images in Docker?

We can use the Docker images command to list all the images in our local machine. The syntax of the command is –

$ docker images
Docker Images
Docker Images

You can see that both the myubuntu images and the ubuntu image that we pulled and created in the above examples have been listed.

How to run containers associated with an image?

We can use the Docker run command to create and run a container associated with the image. The syntax of the Docker run command is –

$ docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Let’s try to run a container of the myubuntu image that we just created.

Docker run command
Docker run command

You can see that as soon as we ran the container, the content of the file has been printed. We have used the –name option to give a name to our container. Let’s try to access the bash of the container by running the command using i and t options which allows us to open the bash of the container interactively.

Docker run command

You can see that we can interact with the container the same way we interact with our local machine.

How to remove Docker images?

To remove Docker images, we can use to different command. These are –

$ docker image rm -f myubuntu:latest

or

$ docker image rmi -f myubuntu:latest

By default, you can only remove those images that do not have a container associated with them. In case if you have one, you can use the force option to remove images forcefully.

Docker Image Remove
Docker Image Remove

Advantages of Docker Images

Docker images have a lot of advantages. Some of them are –

  1. They are portable and platform indpendent. This is so because they contain all the libraries, binaries, and configuration files needed to run an application. Hence, it becomes easy to share Docker images.
  2. They have a multi-layered filesystem. Hence, the image size if very low. Each image layer only incorportes the changes from the previous layer.
  3. Images are consistent. This is so because they are immutable and read-only. To make changes, either we need to change the Dockerfile or create a container and commit the changes.
  4. Image are secure because they have has values. Even we can also digitally sign an image.
  5. Sharing of images is very easily. We can convert them into tarball files or push them to repositories like Dockerhub.

Final Thoughts

We cannot imagine a Docker architecture without Docker images. They are the very heart of the container concept in Docker. Images are just like snapshots of the container application environment. In this article, we have discussed each and every concept related to Docker images in detail. Check out our complete Docker Tutorials.

Recommeded articles –

  1. What is Docker?
  2. Docker Container Lifecycle.
  3. How to install Docker on Ubuntu/Linux?

Leave a Reply