Learn Computing from the Experts | The Rheinwerk Computing Blog

Getting Started with Docker: Basic Principles and Terminology

Written by Rheinwerk Computing | Mar 12, 2025 1:00:00 PM

This blog post explains the most important terms used in the Docker world and provides an overview of how Docker works.

 

Images and Containers

The starting point for the execution of each container is an image. You may already know the term from virtual machines, where a disk image is a file presented to the virtualization system as a hard drive. The virtual machine can set up partitions and file systems there.

 

With Docker, on the other hand, an image provides the basis for the container as a read-only file system. Unlike virtual machines, the running container never changes the image. Instead, any files modified or added by the container end up in a separate overlay file system, which is mapped by its own directory within the Docker base directory on the host.

 

The separation between immutable image files and mutable container files makes it possible to derive any number of containers from an image, which can certainly be executed at the same time.

 

A lot of images are available for download on the internet, especially on Docker Hub, and the vast majority are free of charge. You can help yourself to these images as you would a toolbox: you can derive your own containers from them and even combine them into new images yourself.

 

Docker Hub: Docker Hub is operated by the Docker company, but the images provided there predominantly originate from the Docker community. Having set up a login, anyone can publicly provide images here for free. Although this is a fantastic offer, there’s a lot of junk on Docker Hub in addition to a multitude of great images: test projects, software that’s no longer maintained, and the like. In this respect, you should exercise some caution when selecting images on Docker Hub. Usually, “official” images maintained by Docker are unreservedly recommended. https://hub.docker.com

 

Volumes

A basic concept of Docker is that when images are updated (e.g., because of a new software version), the running container simply gets stopped, and a new container is set up to replace the old one. (Neither the update nor the container restart occurs automatically. You’ll have to take care of that yourself.)

 

As far as the program code contained in the image, this concept is as simple as it is ingenious—but what about the files created during the operation of the container? After all, it’s not acceptable that they’ll all be lost when a new container gets set up.

 

To avoid this, Docker provides volumes, which are directories in the host file system that are separate from the container. Files are stored there that will be preserved when switching from one version to the next, that is, from one container to the next. For example, in the case of a container with a database server, all database files are located in such a volume; in the case of a container with a web server, the HTML documents, PHP scripts, and so on are located there.

 

By default, when you create a new container, Docker automatically sets up an associated volume directory (in the /var/lib/docker/volumes directory or in .local/share/docker/volumes on Linux) and names it with a universally unique identifier (UUID). For the purpose of better management, you can assign volumes their own name or even specify the location of the directory. This way, you avoid long path names that are impossible to remember. If you don’t know where a container’s volume is located, you can use docker inspect to determine this information.

 

Services, Stacks, and Clusters

As long as you run Docker on one machine, the concept of containers is sufficient. However, as soon as it comes to distributing services across multiple machines (via multiple Docker hosts), the administrative overhead increases significantly. To make Docker more scalable in such cases, as well as to implement load-balancing and high-availability features, the concept of services was introduced.

 

A service describes a service or a task. Similar to a container, when you define a service, you specify which image you’re referencing and which command should ultimately be executed. The main difference with containers is that you don’t need to bother about running services yourself as Docker takes care of that. In particular, Docker uses rules to decide on which Docker hosts the service is supposed to be run. (Behind the scenes, of course, to run a service, a container must be set up and started. Services don’t replace containers, but form an additional management layer.)

 

In Docker practice, multiple services are often combined. Only the overall product resulting from this combination can be meaningfully tested or used. Stacks simplify the management of such service groups. The corresponding docker stack command can set up, start, or stop multiple related services together.

 

The basic requirement for using services and stacks is that you assemble a cluster of Docker hosts up front. In Docker terminology, however, we don’t speak of a cluster, but of a swarm. A swarm consists of multiple Docker instances connected by a relatively simple configuration using docker swarm init and docker swarm join. In extreme cases, a swarm can even consist of only a single Docker instance. This is sufficient for initial tests; however, the advantages of a cluster system can’t manifest themselves in the process, of course.

 

An alternative to Docker Swarm is Kubernetes, which is an open-source program developed by Google for managing containers. Kubernetes also supports other container systems, but it’s often used in combination with Docker. Kubernetes is currently much more widely used than Docker Swarm. Learn more about the differences between Kubernetes and Docker Swarm here.

 

docker Command versus Docker Daemon (dockerd)

Docker is implemented as a client-server model. The Docker daemon running in the background is responsible for executing the containers. The name Docker Engine is also commonly used for this program. On Linux, this is the dockerd process. On macOS or Windows, on the other hand, the functions are distributed across several processes whose names begin with com.docker or Docker. In particular, a virtual machine with a tiny Linux distribution must additionally be run on macOS or Windows to provide the functions required for Docker.

 

To control the daemon or Docker Engine, you should use the docker command. It often happens that the Docker daemon and docker run on the same host. However, it’s also possible to use docker to establish a network connection to an external Docker daemon.

 

Linux versus Windows

In a production environment, Docker is most commonly used to run programs from the Linux world on a Linux server (Docker host). Before a program can run productively, however, it must be developed, and you can do that just as well on macOS or Windows, with few restrictions. In other words, you can choose to develop your new web application on a Linux desktop distribution, macOS, or Windows. When everything is running satisfactorily, you can operate the Docker container on a Linux server or in a cloud.

 

While Docker has been established as a tool for Linux-savvy developers for years, the range of Docker images specifically intended for Windows is growing at the same time. These include, for example, a minimal version of Windows Server (the so-called Nano Server), the Internet Information Server (IIS), or ASP.NET. However, such images can only be run with the Docker version for Windows. In some cases, the operating system variant of the host is also checked for licensing reasons. Thus, you can’t try out Nano Server on Windows 10; rather, you need a Windows server instance.

 

From Microsoft’s point of view, this is understandable: Among other things, the company earns its money by selling server licenses. It would be counterproductive to allow a Windows server container to run on a machine that’s not a Windows server. On the other hand, it’s precisely this kind of restriction that makes life arduous for developers and almost forces them into the Linux segment.

 

Switching the Docker Engine between Linux and Windows Containers

A Docker host running on Windows can run both Linux and Windows containers (see the table below)—but not simultaneously! By default, the Windows version of Docker is also configured to run Linux containers.

 

 

If you want to use Windows containers instead, you need to run Switch to Windows containers from the Docker menu (which you can access via the icon in the info area of the taskbar). After the obligatory Windows restart, you can then run Windows containers.

 

Switching back to the Linux world works similarly via Switch to Linux containers, and surprisingly without another Windows restart. Switching between the two worlds is done without any loss of data. As a result, images that have already been downloaded, containers that have been set up, and so on are retained.

 

Virtual Machines versus Containers

Even though virtual machines and containers pursue similar goals, such as running various test programs or server applications on a physical computer as isolated from each other as possible, the way they work is fundamentally different.

 

In each virtual machine, the entire hardware of a PC is replicated by means of software. The virtual machine has the impression of running on a real computer. But this requires a huge number of resources (RAM, disk space, CPU cycles).

 

Containers, on the other hand, directly use the infrastructure of the host system, in particular, its file system and a common kernel. On Linux, this is simply the kernel of the host computer. If, on the other hand, Docker is run on macOS or Windows, a Linux kernel optimized for Docker runs separately from the actual operating system. On Windows, the Windows Subsystem for Linux (WSL2) is used to run this kernel.

 

In a sense, Docker containers run like isolated processes (similar to sandboxes) directly in the host system. The space requirements of containers are usually much smaller than those of virtual machines because the substructure can be reduced to a minimum. Containers also start up much faster.

 

The advantage of virtual machines is that they are better and more securely separated than Docker applications. Docker can only keep up to a limited extent in this respect because the kernel in particular, as a central shared resource, makes complete isolation impossible.

 

On the other hand, the greatly reduced overhead speaks in favor of Docker. In addition, Docker applications can be created and configured within a few seconds on the basis of a script. When it comes to setting up applications in an automated manner, whether for testing or scaling, Docker provides huge advantages over the comparatively cumbersome virtual machines. While with virtual machines it’s usually expedient to combine several related services in one virtual machine, each function can get its own container with Docker. In this context, we often speak of a microservices architecture.

 

Virtualization and containers are by no means mutually exclusive. In practice, for example, it often happens that the Docker Engine itself runs in a virtual machine again.

 

Editor’s note: This post has been adapted from a section of the book Docker: Practical Guide for Developers and DevOps Teams by Bernd Öggl and Michael Kofler. Bernd is a web developer and system administrator who has been using Docker in productive environments for many years. Michael is a specialist book author in German-speaking countries and covers topics from Linux to Swift to IT security.

 

This post was originally published 3/2025.