
Introduction to Docker
Docker is an open source container runtime system based on Linux containers. Linux containers use Linux kernel features such as namespaces, control groups (cgroups), and layered filesystems:
- Namespaces: Namespaces isolate each application from the host and other applications by creating separate environments.
- cgroups: In Linux, cgroups are used to limit applications for a specific set of resources such as memory or processing power.
- Layered filesystems: Layered filesystems consist of reusable layers stacked on top of each other to form the base of a root filesystem. They are the primary technology that enables containers to be lightweight.
Namespaces and cgroups surround the containers that are to be isolated and limited; whereas a layered filesystem consists of what is shared and packaged inside the containers. When you consider the popularity of Docker, the following three essential features make it prominent:
- Speed: Docker containers are lightweight, and their engines work quickly not only on data center servers but also on developer laptops. Therefore, they shorten the time that is required to debug problems, test fixes, and release new versions.
- Ecosystem: The Docker ecosystem enables newcomers to build and run containerized applications. It is possible to find, download, and start a Docker container from the Docker Hub registry in a couple of seconds. Docker Hub is a free-to-use Docker container registry, which is similar to the mobile application store in Apple or Android.
- Usability: Docker makes it easier to run containers for everyone, including developers, quality teams, and operators. It made the motto of Java "build once run everywhere" real with its easy-to-use client and API.
The speed, vibrant ecosystem, and usability features of Docker make it the container runtime that comes to mind first. In order to learn about Docker in detail and use it, we need to cover some fundamental concepts next.
Note
You are required to have Docker Engine installed on your local system before starting on the fundamental concepts and the exercise. Download and install the Docker Desktop based on your local operating system from the Docker website at https://www.docker.com/products/docker-desktop.
The Fundamental Concepts of Docker
In this section, the basic concepts of Docker are explained in detail as some of them are used interchangeably in various blogs and tutorials. Starting from the operating system part of Docker itself to the containers, the fundamental concepts are visualized in Figure 2.2, as follows:

Figure 2.2: The fundamental concepts of Docker
Docker Engine
Docker Engine is the layer on top of the operating system where the containers run. It consists of the Docker Daemon running in the host system and the Docker Client in order to communicate with its daemon service.
Docker Daemon
Docker Daemon is the service that runs on the host system and manages the containers and their interactions with external systems. We can easily check whether the daemon is installed and running on the Docker system by executing the following command:
ps aux |grep docker

Figure 2.3: The process status output filtered for Docker
If you cannot see any process items for Docker in the process status output, you could check for them by restarting the daemon with the commands based on your operating system. If you see a couple of items like in Figure 2.3, it shows that the daemon is working and is accessible by Docker Client.
Docker Client
Docker Client is the tool that is used for interacting with Docker Daemon and, by default, it is accessible by a Docker command in the Terminal. In a system where Docker is installed and running, the version and API information can be checked using the following command:
docker version

Figure 2.4: The output of the docker version command
This lists the version of the client and server with the corresponding API versions and further information about the runtime environment. This command is helpful if any unexpected API mismatches occur between the client and the daemon.
Docker Images
Docker images are read-only packages, which can include operating system libraries and application requirements, if necessary. Docker images are defined using Dockerfiles which include stepwise actions on the base image. Dockerfiles are used when Docker images are built, and each step that is specified in a Dockerfile is executed on the base image. Official and community-maintained images are designed to be stored in the Docker registry, and Docker Hub is the official one; for instance, Ubuntu images can be checked in the Docker registry, as follows:

Figure 2.5: The official Ubuntu Docker image in Docker Hub
The Docker registry page for Ubuntu lists all of the available versions and quick-start information to run containers using an Ubuntu image. It is possible to download any Docker image from the Docker registry in a couple of seconds, and it is one of the reasons that makes the Docker environment a popular one.
Docker Containers
Docker containers are running instances of Docker images that consist of an execution environment for applications. They are expected to run many instances of the same Docker image; in other words, multiple Docker containers. Two essential features are added to containers in addition to the images; first, since Docker images are read-only, Docker containers include an additional filesystem layer to enable read-and-write capabilities. Additionally, a network interface is attached to those containers with an available IP so that containers are reachable from the host system and from outside. The flow of Docker images to the registry, and then to the containers is summarized in Figure 2.6:

Figure 2.6: The flow of the Docker container and image
In the following exercise, we will combine these fundamental concepts in order to run and manage a "Hello World" container in Docker.
Exercise 5: Creating a "Hello World" Container in Docker
In this exercise, we aim to create and manage a "Hello World" container in Docker Engine.
To complete the exercise, we need to ensure the following steps are executed:
- Ensure that Docker is working as expected by running the following command:
docker version
Figure 2.7: The output of the docker version command
Here, you should see both the client and server version with their matching API versions in order to operate in harmony. In Figure 2.7, both the client and server have the same version of 18.09.3 and the same API version of 1.39, which indicates that our Docker engine is working.
- Create a hello-world container by running the following command:
docker run hello-world
Figure 2.8: The output of docker run hello-world
In Figure 2.8, the first line indicates Unable to find image 'hello-world: latest' locally, which is to be expected if this container image is never used locally. In the following lines, the Docker image is downloaded from the registry, which is indicated by "latest: Pulling from library/hello-world". After downloading, Hello from Docker! shows the first outputs of the running containers. These stages are also described in the four steps in the output.
- Check the Docker process status by executing the following command:
docker ps

Figure 2.9: The output of docker ps
Since the hello-world container has been started and completed, there is no container listed in the output. When the same command is used with the --all flag to show all the containers, the hello-world container is expected to be listed:
docker ps --all

Figure 2.10: The output of docker ps --all
The container with ID b06d40f39b58 has an Exited (0) 3 minutes ago status, which shows that it was completed successfully.
In this exercise, we have demonstrated how to run a simple Docker container and check its status. In addition, we have shown how the Docker image is downloaded from the Docker registry automatically and is ready to reuse locally. In the following section, we will explain how to build a Docker container and publish it to the Docker registry in order to show how applications are built and released as Docker containers.