Kahibaro
Discord Login Register

2.2 Containers

From Image to Running Environment

A container is a running instance of an image. While an image is a static template with everything your application needs, a container is that template brought to life as a process on your system. Each time you start an image, you create a container that has its own isolated filesystem, its own configuration, and its own lifecycle.

When you run a container, Docker takes the image, adds a thin writable layer on top of the read only layers from the image, and starts the process defined by that image. This writable layer is where file changes inside the container are stored for as long as the container exists.

Containers feel like lightweight virtual machines, but they are simply isolated processes that share the host operating system kernel. Because of this, containers start quickly, use fewer resources, and are easier to create and destroy.

A container is not a virtual machine. It is a process that runs in isolation on the host kernel, created from an image plus a temporary writable layer.

Isolation and Namespaces

The isolation that makes a container feel self contained is largely provided by operating system features called namespaces. Namespaces limit what a container can see and interact with on the host.

For example, process namespaces ensure that processes inside a container only see other processes in the same container, not every process on the host. Network namespaces give the container its own network stack view so it can have its own IP address and ports. Mount namespaces make the filesystem inside the container appear separate from the host even though it is built from layers that live on the host.

From inside the container, it looks as if there is a complete operating system environment. In reality, you have a process with carefully restricted visibility of the host system.

Control Groups and Resource Limits

While namespaces handle visibility, control groups, often shortened to cgroups, handle resource usage. Cgroups allow Docker to account for and limit the amount of CPU time, memory, and other resources that containers can use.

If you run many containers on a single machine, cgroups prevent one misbehaving or busy container from taking all the CPU or memory and starving others. Although you can run containers without strict limits, in real environments it is common to use cgroups to keep resource usage predictable and fair.

Container Filesystem and Ephemeral State

Each container gets its own filesystem view built from the image layers plus a writable layer on top. The image part is shared and read only. The writable layer holds all file changes that occur while the container is running. When you install packages inside a container, write logs to the default paths, or create new files, they land in that writable layer.

This writable layer only exists for the life of the container. When you remove the container, its writable layer disappears and with it all data that was not explicitly stored outside the container.

Anything stored only inside a container’s writable layer is temporary. When the container is removed, that data is lost.

Persistent data is handled separately through mechanisms that connect external storage to the container’s filesystem view. These are discussed in detail in the data and volumes chapters, so here it is enough to remember that the container’s own layer is not designed for long term storage.

Container Identity and Lifecycle

Each container has a unique identifier, usually shown as a long hexadecimal string, and can also have a human friendly name. The identifier and name allow you to manage the container while it exists. Under the hood, Docker keeps metadata about the container, including which image it came from, which command it runs, what mount points it has, and its networking details.

A container lifecycle typically goes through creation, running, stopping, and removal. Creation prepares the container from an image and defines its configuration. Running starts the main process. Stopping ends that process. Removal deletes the container’s metadata and its writable layer.

It is important to understand that a container is tied to the process defined by its configuration. When that main process exits, the container is considered stopped. You can usually start it again with the same settings, but if you remove it, the transient state is gone and a new container will be required for the next run.

One Main Process per Container

Conceptually, each container is built around a single main process. That process is the one Docker monitors to decide whether the container is running or stopped. You can run additional processes inside the same container, but they depend on that main process for the container to remain alive.

For example, a web server container usually has the web server process as its main process. If that process crashes or exits, Docker marks the container as stopped. Any other processes that were running inside it are also gone because the container’s environment is no longer active.

The life of a container is tied to its main process. When the main process exits, the container stops, even if other processes were running inside it.

This focus on one main process keeps containers simple to reason about and easier to replace when something goes wrong.

Immutable Infrastructure and Container Replacement

Containers are designed to be disposable. Instead of logging into a container and manually changing its configuration, the usual approach is to modify the image definition, recreate the image, and then start new containers from that updated image.

If a container becomes misconfigured or fails in some unexpected way, the recommended action is to stop it and start a new one. Since containers start quickly and creation is cheap, replacement is more reliable than repair. This idea of replacing rather than mutating running instances is sometimes called immutable infrastructure.

Because containers are cheap to create and remove, scaling an application often means running more identical containers from the same image and configuration, rather than making one container bigger or more complex.

Containers and the Host System

Although containers are isolated environments, they still run directly on the host system and share its kernel. This gives them their performance advantages but also means they interact closely with host level resources.

Containers use host CPU, memory, and storage. They can be given access to host devices such as GPUs or disks. They also depend on host level security settings and kernel configuration. In practice, a container can only do what the host allows. This is important for security and for performance tuning, and it also explains why containers on the same host must be compatible with the host operating system kernel.

From a practical perspective, this means that if the host has a Linux kernel, containers will also expect Linux system calls. Other platforms use an additional layer to provide a compatible environment, but the container concept itself still relies on sharing a kernel rather than simulating an entire machine.

Containers as Building Blocks

Containers are rarely used alone in real world applications. Instead, each container is responsible for a focused role, such as running a web server, a database, or a background worker, and multiple containers work together to form a complete system.

This modular approach lets you update or scale each part independently. If the web layer needs more capacity, you run more web containers without changing the database container. If a dependency changes, you build a new image and replace only the affected containers.

In this way, containers become the basic building blocks of modern applications, small, isolated, and easy to combine, all created quickly from images and managed through a consistent lifecycle.

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!