Container and image vocabulary
Tags: docker, beginners, devops, programming
Published: 2023-04-03 10:00:00

*Kubernetes is a container orchestration system which is used to manage containers grouped in pods which are hosted on nodes. To do that Kubernetes uses an agent called kubelet which uses a Docker (or another container runtime or container engine) which uses a container runtime (once again?) to manage the container lifecycle.*

**🛑 HOLD ON!**

So much layers, terms, and dependencies here. It is not easy to understand how all these components work together. Especially, when some of terms are used interchangeably.

**😉 Don't worry.**

I will clarify those uncertainties in this series. I will take you on a journey to understand the concept of containers and containerization, and their terms one by one. From bottom to top. From the smallest units, which are system resources and process. At the end of the day, they compute and store your data, not Kubernetes.

In this post I will explain the terms related to containers and images, and a bit of the operating system.

**🧭 Let's start the journey!**

## Table of contents

- [Table of contents](#table-of-contents)
- [Terminology on the schema](#terminology-on-the-schema)
- [Operating system specific terms](#operating-system-specific-terms)
  - [process](#process)
  - [resource](#resource)
  - [namespace](#namespace)
  - [cgroups](#cgroups)
  - [SELinux](#selinux)
  - [AppArmor](#apparmor)
  - [SELinux vs AppArmor](#selinux-vs-apparmor)
  - [union mount](#union-mount)
  - [copy-on-write](#copy-on-write)
  - [overlayFS](#overlayfs)
- [Containers and images specific terms](#containers-and-images-specific-terms)
  - [container](#container)
  - [volume](#volume)
  - [image](#image)
  - [base image](#base-image)
  - [parent image](#parent-image)
  - [layer](#layer)
  - [blob](#blob)
  - [writable layer](#writable-layer)
  - [build](#build)
  - [context](#context)
  - [Dockerfile](#dockerfile)
  - [Dockerfile instruction](#dockerfile-instruction)
  - [entrypoint / cmd](#entrypoint--cmd)
- [Ending](#ending)

## Terminology on the schema

I prepared a map 🗺️ for you to not get lost in the terminology journey.
The following schema shows the relationship between the terms.

![schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hay0jmzn22mtwn0tjb5s.png)

\* Docker is only one of container runtimes and can do much more than presented in the map. I will explain it with details in the next post from this series.

## Operating system specific terms

### process

[🔗](https://en.wikipedia.org/wiki/Process_(computing))

A process of an operating system is an instance of a computer program that is being executed by one or many threads. It is a basic unit of work.

### resource

[🔗](https://en.wikipedia.org/wiki/Process_(computing)#Representation)

A resource is a hardware of software component managed by an operating system. Resources are allocated to [processes](#process) to perform some work.

Sample Linux resources:

- net - network interfaces
- mnt - file system mount points
- pid - process ID space
- uts - hostname and NIS domain name
- user - user and group IDs
- ipc - inter-process communication mechanisms.

### namespace

[🔗](https://www.nginx.com/blog/what-are-namespaces-cgroups-how-do-they-work/)

A Linux namespace is functionality of the Linux kernel that isolates and virtualizes [system resource](#resource). [Processes](#process) can only interact with resources or processes that are part of the same namespace. Namespaces exist for each type of resource.

Namespaces provide isolation of system resources, and [cgroups](#cgroups) allow for fine‑grained control and enforcement of limits for those resources.

### cgroups

[🔗](https://towardsdatascience.com/the-power-of-linux-cgroups-how-containers-take-control-of-their-resources-ba564fef13b0)

A control group (cgroup) is a Linux kernel feature that limits, accounts for, and isolates the usage of [resources](#resource) by a collection of [processes](process). Docker relies on *cgroups* to control and isolate resource limits.

In the context of [containers](#container), cgroups limits the resources that each container can consume. cgroups ensures the container has the resources it needs to function properly.

### SELinux

[🔗](https://www.redhat.com/en/topics/linux/what-is-selinux) [🔗](https://www.arhea.net/posts/2020-04-28-selinux-for-containers)

SELinux (Security-Enhanced Linux) defines access controls for the applications, [processes](#process), and [files](#resource) on a system. It uses security policies, which are a set of rules that tell SELinux what can or can’t be accessed. When an application or process makes a request to access an object, like a file, SELinux checks with an access vector cache (AVC), where permissions are cached for subjects and objects. If SELinux is unable to make a decision about access based on the cached permissions, it sends the request to the security server. SELinux supports mandatory access control (MAC).

SELinux is used by [containers](#container) to control accesses withing them.

### AppArmor

[🔗](https://www.apparmor.net/) [🔗](https://cloud.google.com/container-optimized-os/docs/how-to/secure-apparmor)

AppArmor (Application Armor) is security module that you can use to restrict the capabilities of [processes](#process) running on the host operating system. Each process can have its own security profile. The security profile allows or disallows specific capabilities, such as [network](#resource) access or [file](#resource) read/write/execute permissions. It proactively protects the operating system and applications from external or internal threats. AppArmor supplements the traditional Unix discretionary access control (DAC) model by providing mandatory access control (MAC).

For any given [container](#container), you can apply either the default AppArmor security profile, or a custom security profile that you provide.

### SELinux vs AppArmor

Most popular Linux distributions contain pre-installed one or both of those security modules.

> You could have gotten hold of an impression that SELinux and AppArmor were remarkably similar to each other. It is true. Here you can dive into the comparison between them: <https://www.maketecheasier.com/selinux-vs-apparmor/>.

### union mount

[🔗](https://en.wikipedia.org/wiki/Union_mount)

In computer operating systems, union mount is a technique to mount multiple directories into one that appears to contain their combined contents.

### copy-on-write

[🔗](https://docs.docker.com/glossary/)

It is a technique used to optimize the performance of file systems by copying of a resource only when it is modified. Non-modified resources are shared between the original and the copy of an operation.

### overlayFS

[🔗](https://en.wikipedia.org/wiki/OverlayFS)

OverlayFS is the [union mount](#union-mount) implementation included in the Linux kernel since the version 3.18. It implements the [copy-on-write](#copy-on-write) technique by overlaying file system layers on top of another one and interacting with the merged result.

OverlayFS is used by Docker to create [images](#image) and [containers](#container).

## Containers and images specific terms

### container

[🔗](https://docs.docker.com/get-started/)

A container is a running instance of an [image](#image). It is a standardized package containing software along with dependencies, configuration, data, and everything that is needed to run.
From the operating system point of view, a container represents an isolated [process](#process) (or group of processes) that exists in its own [namespace](#namespace). Processes inside the container do not see processes outside it and vice versa. The container cannot access [resources](#resource) belonging to another container or process resources outside the container.

### volume

[🔗](https://docs.docker.com/storage/volumes/)

A volume is a directory on a host machine that is mounted into one or more [containers](#container). It is used to store persistent data outside of the container. It is independent of the container lifecycle. There are three types of Docker volumes:

- **host volume** - lives on the Docker host file system and can be accessed from within the container
- **named volume** - is managed by Docker, where it is created on disk, but is given a name
- **anonymous volume** - is similar to the named volume, but it can be difficult to reference the same volume over time; the volume is managed by Docker, where the files are stored.

### image

[🔗](https://docs.docker.com/get-started/)

An image is a read-only template that is used to create a [container](#container). It contains an ordered collection of changes to the root file system and the corresponding execution parameters for use at **container runtime**. The change of the file system is called a [layer](#layer). They are stacked on top of each other starting from a [base image](#base-image) or from scratch.

An image is [built](#build) using a [Dockerfile](#dockerfile).

### base image

[🔗](https://docs.docker.com/glossary/)

A base image does not have a specified [parent image](#parent image) in its [Dockerfile](#dockerfile). It is created using a Dockerfile with the `FROM scratch` directive.

The base image is usually the latest version of an operating system. It is usually a minimal [image](#image), which contains only the operating system and few basic tools.

### parent image

[🔗](https://docs.docker.com/glossary/)

A parent image is an [image](#image) that is used by another. It is specified in the `FROM` directive in a child [Dockerfile](#dockerfile).

### layer

[🔗](https://docs.docker.com/glossary/)

A layer is a modification of an [image](#image), represented by a [Dockerfile instruction](#dockerfile-instruction). To create the final image, layers are sequentially applied to the [parent image](#parent-image) or to the root. When the image is updated or rebuilt, only changed layers need to be updated. Unchanged layers are cached locally to be reused.

### blob

[🔗](https://docs.docker.com/registry/spec/api/)

A blob is an immutable binary large object. Blobs are used to store content of the [image](#image) [layers](#layer).

### writable layer

[🔗](https://docs.docker.com/storage/storagedriver/#container-and-layers/)

When a [container](#container) is created, a writable layer is created on top of the [image](#image). It is a [layer](#layer) that can be modified by the container to store changes made to the container. The writable layer is discarded when the container is deleted.

### build

[🔗](https://dev.to/thakkaryash94/how-many-ways-to-build-a-container-image-4g3p)

The process of building a Docker [image](#image) using a [Dockerfile](#dockerfile) and a [context](#context).

Sample tools that implement the build process:

- [docker build](https://docs.docker.com/engine/reference/commandline/build/)
- [buildah](https://github.com/containers/buildah)
- [img](https://github.com/genuinetools/img)
- [kaniko](https://github.com/GoogleContainerTools/kaniko)
- [podman](https://podman.io/)

### context

[🔗](https://docs.docker.com/engine/reference/commandline/build/)

[Build](#build)’s context is a set of files located in the specified `PATH` or `URL`. The build process of an [image](#image) can refer to any files in the context. For example, your build can use the [Dockerfile](#dockerfile) `COPY` [instruction](#dockerfile-instruction) to reference the file in the context.

### Dockerfile

[🔗](https://docs.docker.com/engine/reference/builder/)

Dockerfile is a text file that contains [instructions](#dockerfile-instruction) for [building](build) an [image](#image) in the order that they are written in the file.

### Dockerfile instruction

[🔗](https://docs.docker.com/engine/reference/builder/)

A Dockerfile instruction is a command that is executed during the [build](#build) process. The instructions are executed in the order they are written in the [Dockerfile](#dockerfile). An instruction can be: `FROM`, `RUN`, `CMD`, `LABEL`, `EXPOSE`, `ENV`, `ADD`, `COPY`, `ENTRYPOINT`, `VOLUME`, `USER`, `WORKDIR`, `ARG`, `ONBUILD`, `STOPSIGNAL`, `HEALTHCHECK`, `SHELL`.

### entrypoint / cmd

[🔗](https://docs.docker.com/engine/reference/builder/#entrypoint) [🔗](https://docs.docker.com/engine/reference/builder/#cmd)

If you want your [Dockerfile](#dockerfile) to be able to run without passing additional arguments to the `docker run` command, you must specify `ENTRYPOINT`, `CMD` [instructions](instructions) of both.

- `CMD` is a statement that is run by default when the [container](#container) is started, but can be easily overridden if the container is started with a command.

- `ENTRYPOINT` is set to a single command. Even if you don't specify `ENTRYPOINT`, it can be inherited from a [parent image](#parent-image). It is not overridden even if the container is started with a command. To override `ENTRYPOINT` you can use the `--entrypoint` option of the `docker build` command.

The instructions are reduced to run the command according to the pattern: `<ENTRYPOINT> <CMD>`. Therefore, `CMD` can be used to pass default arguments for the command in `ENTRYPOINT`.

## Ending

Pretty much terms you just learned, aren't they? I gathered them from different sources for you to have a quick reference.

The list is not complete, but it should be enough for you to jump into the world of Docker right now. You've just learned terminology of container components.

Next time I will show you what kind of tools manage them. You will get know what is and what isn't a Docker.
What is the difference between a container engine, a container runtime, and Docker Engine? How does Kubernetes interact with Docker? Does it even use Docker?

I hope you enjoyed this article. If you found it helpful or just liked it, share it with your friends.