Developer
developerDockerfiles, Docker Compose for local dev, debugging with exec/logs, volume mounts for hot reload, and pushing images to registries.
Docker Core · companion to Unix Core & DevOps
Internals-first guides for developers, DevOps engineers, and architects—what Linux actually does when you docker run, why layers cost disk and cache, and what breaks in production.
You shipped code that passed CI, passed QA, and crashed in production because prod ran a different libc, a different JDK patch level, or a missing libssl. VMs solved isolation but each one carries a full guest OS—heavy, slow to boot, expensive to patch.
Containers package your app and its dependencies into an immutable image, then run it as an isolated process on a shared Linux kernel. Same bytes everywhere: laptop, CI runner, staging, prod. Think of an image as a class and a container as an instance—one blueprint, many running copies, each with its own filesystem view and resource budget.
A VM runs a hypervisor + guest OS + your app. A container runs your app directly on the host kernel, isolated by namespaces and cgroups—not by virtualizing hardware.
┌─── VIRTUAL MACHINE ───────────────────┐ ┌─── CONTAINER ─────────────────────────┐
│ App A App B │ │ App A App B │
├───────────────────────────────────────┤ ├───────────────────────────────────────┤
│ Guest OS Guest OS (full OS) │ │ Container libs Container libs │
├───────────────────────────────────────┤ ├───────────────────────────────────────┤
│ Hypervisor (KVM/VMware) │ │ Docker Engine / containerd / runc │
├───────────────────────────────────────┤ ├───────────────────────────────────────┤
│ Host Linux Kernel │ │ Namespaces + cgroups + OverlayFS │
├───────────────────────────────────────┤ ├───────────────────────────────────────┤
│ Physical hardware │ │ Host Linux Kernel │
└───────────────────────────────────────┘ ├───────────────────────────────────────┤
│ Physical hardware │
└───────────────────────────────────────┘
| Dimension | Virtual machine | Linux container |
|---|---|---|
| Isolation mechanism | Hardware virtualization + guest kernel | Namespaces + cgroups on shared kernel |
| Startup time | Minutes (boot guest OS) | Milliseconds (fork + mount) |
| Memory overhead | GB per VM (full OS) | MB (process + writable layer) |
| Density per host | Tens of VMs | Hundreds of containers |
| Kernel sharing | Each VM has its own kernel | All containers share host kernel (Linux only) |
| Security boundary | Stronger (hardware + guest kernel) | Weaker—kernel bugs can affect all containers |
Containers win on speed, density, and portability. VMs win on hard multi-tenant isolation and running non-Linux kernels. Most teams use both: VMs for tenant boundaries, containers for app packaging inside them.
Containers are not mini-VMs. They are isolated processes. If asked "how is a container isolated?", name the Linux primitives: PID, NET, MNT, UTS, IPC, USER namespaces + cgroup resource limits.
Docker popularized containers, then donated the runtime to the community. Today the stack is layered: CLI and build tools on top, OCI-compliant runtime at the bottom, Linux kernel underneath everything.
When you docker run nginx, the CLI talks to dockerd over a Unix socket. dockerd asks containerd to create a bundle (rootfs + config.json per the OCI Runtime Spec). containerd invokes runc create then runc start. runc calls clone() with CLONE_NEW* flags and writes cgroup limits to /sys/fs/cgroup/.
Standard for how to launch a container: process args, mounts, namespaces, cgroups, seccomp—implemented by runc, crun, kata.
Layer tarballs + manifest + config JSON. Content-addressed by SHA256 digest. Same format Docker Hub and every registry uses.
Registry HTTP API: /v2/<name>/manifests/<ref> and blob push/pull. ECR, GCR, Harbor all comply.
K8s nodes don't run dockerd—they call containerd (or CRI-O) via the CRI. Your Dockerfile still builds the image; K8s pulls and runs it.
Daemonless, rootless-first alternative. Same OCI images, no central dockerd—popular on RHEL and OpenShift developer workstations.
Docker is more than docker run—understand which tool owns build, orchestration, distribution, and security scanning in your pipeline.
GitHub Actions runs CI jobs in ephemeral containers built from your Dockerfile or service images. Netflix uses containers (Titus on AWS) for batch and streaming workloads. Google invented distroless images because they run billions of containers and need minimal attack surface.
Enable BuildKit permanently: add "features": { "buildkit": true } to ~/.docker/daemon.json or export DOCKER_BUILDKIT=1. You get cache mounts and secret mounts that never touch image layers.
From dotCloud side project to industry standard—and the deliberate unbundling of the runtime from the Docker brand.
Solomon Hykes demos lightweight containers at PyCon. LXC + namespaces + union filesystems packaged for developers.
Central image registry launches. Fig (acquired) becomes Docker Compose—define multi-container apps in YAML.
Docker donates runc to the Open Container Initiative. Runtime, image, and distribution specs prevent vendor lock-in.
Native clustering built into Docker Engine. Largely superseded by Kubernetes but still used for simple multi-node setups.
Docker splits into Moby (open-source assembly) and Docker CE/EE products. containerd donated to CNCF—becomes K8s default runtime.
BuildKit becomes opt-in default builder. Parallel multi-stage builds, inline cache, --mount=type=secret.
ARM64 support mainstream. Multi-arch docker buildx workflows become essential for Apple Silicon devs shipping to amd64 prod.
Supply chain security: CVE dashboards, base image recommendations, policy gates in CI and Hub.
Docker Desktop and Engine 25+ use containerd for image storage by default—faster pull, better multi-platform manifest handling.
Every container starts the same way—whether you typed the command or Kubernetes did it via the CRI.
docker run
CLI parses flags, sends Create + Start to dockerd API
dockerd
Pull image, create network endpoint, allocate volume mounts
containerd → runc
Snapshot OverlayFS layers, write OCI bundle, clone() + exec
Container process
PID 1 in isolated namespaces, cgroup limits applied
flowchart TB
subgraph user["Your machine"]
CLI["Docker CLI\ndocker run / compose"]
end
subgraph engine["Docker Engine"]
D["dockerd\nAPI · networks · volumes"]
C["containerd\nimages · snapshots"]
S["containerd-shim"]
R["runc\nOCI runtime"]
end
subgraph kernel["Linux kernel"]
NS["namespaces"]
CG["cgroups v2"]
OV["OverlayFS"]
end
P["Container process\nPID 1"]
CLI --> D
D --> C
C --> S
S --> R
R --> NS
R --> CG
R --> OV
R --> P
$ docker run -d --name web -p 8080:80 --memory 256m nginx:1.25-alpine Unable to find image 'nginx:1.25-alpine' locally 1.25-alpine: Pulling from library/nginx Digest: sha256:a21a...c4f2 Status: Downloaded newer image for nginx:1.25-alpine a3f8c2e91b04d7f6e8a1c9b2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2 $ docker inspect --format '{{.State.Pid}}' web 48291 $ ls -la /proc/48291/ns/ lrwxrwxrwx 1 root root 0 ipc -> ipc:[4026532987] lrwxrwxrwx 1 root root 0 mnt -> mnt:[4026532985] lrwxrwxrwx 1 root root 0 net -> net:[4026532988] lrwxrwxrwx 1 root root 0 pid -> pid:[4026532986] lrwxrwxrwx 1 root root 0 uts -> uts:[4026532984]
Running containers without --memory or --cpus limits lets one container consume the entire host—OOM kills other containers or the host itself. Always set resource limits in production, even on single-server Compose deployments.
Never run production workloads with --privileged. It grants nearly all capabilities and disables most seccomp filters—one container escape compromises the host.
Thirteen deep-dive chapters plus cheat sheets. Recommended path: Internals → Images → Containers → Networking, then Compose, security, and CI/CD as your role requires.
Learning path: Internals · Images · Containers · Networking · Dockerfile Patterns
Dockerfiles, Docker Compose for local dev, debugging with exec/logs, volume mounts for hot reload, and pushing images to registries.
CI/CD pipelines, multi-stage builds, BuildKit cache, image scanning, registry management, runtime security, and production Compose deployments.
Container strategy, base image governance, Docker vs Kubernetes vs Podman decisions, security posture, and VM-to-container migration patterns.
Linux namespaces, cgroups v2, OverlayFS, runc, containerd, rootless Docker.
Layer caching, Dockerfile instructions, multi-stage builds, BuildKit, image optimization.
Lifecycle states, run flags, PID 1 problem, debugging, resource limits.
Bridge internals, DNS, port publishing, network drivers, segmentation.
Volumes vs bind mounts, CoW costs, database persistence, backup patterns.
Java, Node, Python, Go, Nginx—opinionated multi-stage recipes and anti-patterns.
Compose Spec, local dev stacks, multi-env overrides, watch mode, production patterns.
OCI distribution, ECR/Harbor, signing, SBOM, scanning, promotion strategy.
Threat model, capabilities, seccomp, secrets management, image hardening checklist.
GitHub Actions, GitLab CI, layer cache strategies, hadolint, image promotion.
Standalone vs K8s, logging, health checks, blue-green, RHEL/Podman/OpenShift.
Developer, DevOps, and architect quick references with copy-to-clipboard.