Skip to content

Zoom-in: Docker Container

Karify98·
Cover Image for Zoom-in: Docker Container

docker run, app starts immediately. On a local machine, a colleague's machine, or a production server — the same result.

graph LR
    D(["🐳 docker run"]) -->|"runs"| C(["📦 Container"])
    C -->|"works everywhere"| R(["✅ Result"])
    style D fill:#1e293b,stroke:#475569,color:#cbd5e1
    style C fill:#1e293b,stroke:#475569,color:#cbd5e1
    style R fill:#1e293b,stroke:#475569,color:#cbd5e1

Zoom in on the black box.


Layer 1 — The root problem: "works on my machine"

Before Docker, the environment was something that couldn't be controlled. An app ran on the dev machine because it had the right Python version, the right dependency, the right environment variables. The production server was missing one thing — app crashes.

graph LR
    Dev["💻 Dev\nPython 3.11\nlib-v2.3"] -->|"works"| OK["✅ Works"]
    Prod["🖥️ Server\nPython 3.9\nlib-v1.8"] -->|"crash"| Fail["❌ ImportError"]

    style Dev fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style Prod fill:#3b1a1a,stroke:#ef4444,color:#fca5a5
    style OK fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style Fail fill:#3b1a1a,stroke:#ef4444,color:#fca5a5

The original solution was virtual machines (VMs) — bundle the entire operating system with the app. It worked, but each VM weighs several GB and takes minutes to boot.

Problem left: need VM-level isolation but much lighter and faster.

Layer 2 — Namespaces: isolation without a VM

Containers aren't a new technology — they use features built into the Linux kernel since 2008: namespaces.

Namespaces partition the kernel into separate "spaces" for each process:

PID Each container has its own process list — processes inside can't see processes outside
NET Each container has its own network interface and IP — communicates via a bridge network Docker creates
MNT Each container sees its own filesystem — can't see files from other containers or the host
UTS Each container has its own hostname

There's no separate operating system — all containers share the host's Linux kernel. This is why containers are so much lighter than VMs.

Problem left: processes are isolated, but what if one container consumes all CPU or RAM?

Layer 3 — cgroups: resource limits

cgroups (control groups) is a Linux kernel feature to limit and monitor resources for a group of processes.

graph TD
    Host["🖥️ Host (16GB RAM, 8 CPU)"]
    Host --> C1["📦 Container A\n≤ 2GB RAM\n≤ 2 CPU"]
    Host --> C2["📦 Container B\n≤ 4GB RAM\n≤ 4 CPU"]
    Host --> C3["📦 Container C\n≤ 1GB RAM\n≤ 1 CPU"]

    style Host fill:#1a3a2a,stroke:#22c55e,color:#86efac
    style C1 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style C2 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd
    style C3 fill:#1e3a5f,stroke:#3b82f6,color:#93c5fd

docker run --memory=2g --cpus=2 translates into cgroup rules for the Linux kernel. When a container exceeds its RAM limit, the kernel's OOM killer terminates the process inside the container — without affecting other containers.

Problem left: processes are isolated, resources are bounded — but where does the container's filesystem come from?

Layer 4 — Union filesystem: image layers

A container image isn't a single file — it's a stack of layers.

Layer 4: App code           (5MB)   ← changes most often
Layer 3: pip dependencies   (120MB)
Layer 2: Python 3.11        (50MB)
Layer 1: Ubuntu base        (29MB)  ← changes least

When pulling an image, Docker only downloads layers not already present. When building a new image with only app code changes, layers 1–3 are reused from cache — much faster builds.

When a container runs, Docker adds a writable layer on top. All changes inside the container (writing files, creating directories) happen in this layer — the image layers below are unchanged. When the container stops, the writable layer is discarded.


Full picture

From docker run to a process running inside a container.

sequenceDiagram
    participant CLI as docker run
    participant D as Docker Daemon
    participant K as Linux Kernel

    CLI->>D: docker run --memory=2g myapp
    D->>K: Create PID namespace
    D->>K: Create NET namespace + bridge interface
    D->>K: Create MNT namespace + union filesystem
    D->>K: Create cgroup (≤ 2GB RAM)
    D->>K: fork() + exec() process in namespace
    K-->>CLI: Container ID abc123

    Note over K: Process runs in an isolated "bubble"<br/>but still uses the host's kernel

A container is not a VM — no hypervisor, no guest OS. Just a Linux process with specially configured namespaces and cgroups.


Three common misconceptions

Containers and VMs are the same, just different names

VMs run their own OS — fully isolated, minutes to boot, several GB each. Containers share the host kernel — lighter, faster, but less isolated. A process escaping a container namespace (container escape) can affect the host — not possible with a VM.

Docker images are completely immutable

The image layers below are immutable, but the writable layer while the container is running is not. Data written inside a container is lost when the container stops — use a volume or bind mount to persist data. Many people lose data on container restart because of this misunderstanding.

Containers are secure by default

Containers run as root inside by default unless configured otherwise. If a container is compromised, an attacker has root inside the container — and with a volume mount or privileged mode, can escalate to the host. Always run containers with a non-root user in production.

Takeaway

Containers exist because the Linux kernel already had the tools to create isolated environments without VMs: namespaces for isolation, cgroups for resource limits, union filesystem for reusable image layers. Docker is just a friendly interface that packages all three together.

When debugging a container, the right question is: "is the problem in the namespace, the cgroup, or the filesystem layer?" — docker inspect, docker stats, and docker exec show the state of each layer.


Article assisted by Amy 🌸 - AI Assistant. Content reviewed by the author.

Related Posts