Container Fundamentals
Stdlib for software: pack once, run anywhere
A container packages an app with its runtime into a portable, isolated unit sharing the host kernel. Images are layers; containers are running instances with cgroups and namespaces keeping them apart.
What you will learn
- Explain image layers, containers, registries, runtimes
- Distinguish container vs VM isolation
- Run, exec, and manage a container without confusion
An image is an immutable stack of read-only layers (build deps, app, config). A container = image + writable layer + isolated processes (namespaces) with resource limits (cgroups), all sharing the kernel. Docker is tooling + runtime; OCI is the standard interop layer.
What is this?
Layers: each COPY/RUN instruction adds a layer; images are hashes of ordered layers. Image manifest: config + layers + tags/refs. Runtimes: containerd/runc (OCI), docker (client+daemon), podman (daemonless). Isolation: namespaces (PID, NET, MNT, UTS, IPC, USER) + cgroups (CPU, mem, pids, io). Image pull: docker run pulls by reference digest:tag; layers cached. Lifecycle: build → tag → push → pull → run → stop → remove; container filesystem dies with the container unless volumes.
Why do you need it?
- Portability: dev laptop and prod rel env differ only in the host OS.
- Isolation at lower cost than VMs: kernel-sharing means seconds, not minutes, startup.
- Immutable artifacts + reproducible builds tame 'works on my machine'.
- Continuous delivery: same image tested in CI runs in prod unchanged.
Mental model
A frozen meal with airtight layers and a 'contains milk' label
Container image layers
Each layer (base, sauce, toppings) is stacked; the final product (image) is immutable. Anyone can reheat it (run) identically on any compatible oven (host runtime).
How it works
- Build: each instruction commits a new read-only layer.
- Registry: stores/strips layer digests; pull fetches only missing layers.
- Run: runtime creates namespaces + cgroups, mounts the union filesystem, starts PID 1.
- Process lives in an isolated view; host kernel mediates CPU/mem via cgroups.
- Stop/remove: cgroup torn down, writable layer deleted unless volumes kept.
Image → container.
Examples
Run and move a container
docker build -t myapp:1.0 . # build layersdocker push ghcr.io/acme/myapp:1.0docker run -d --name web -p 8080:8080 myapp:1.0docker exec -it web sh # peek insidedocker logs web --tail 100Container move from machine to machine is just a pull followed by a run.
In production
- Identical app across dev/stage/prod with pinned multiarch images.
- CI builds publish images to a private registry for immutable release.
- Migration to managed container runtimes with the same image OCI contract.
Best practices
- Prefer slim/distroless base images — smaller attack surface and pulls.
- Pin image digests (sha256:) in production; tag floats are hazards.
- Run as non-root with read-only root FS where possible.
- Order Dockerfile steps caching-first: deps before source changes.
- Export healthy/ready signalling to the orchestrator, not PID 1 agreement.
Common mistakes
- Treating the container like a VM (installing packages at runtime).
- Building images with the kitchen sink and bloating every pull.
- Forgetting the app must signal lifecycle — SIGTERM grace, not abrupt kill.
- Holding state inside the writable layer then losing it on redeploy.
Debugging tips
- docker inspect reveals mounts, network mode, env, restart policy — read it before guessing.
- Container runs then exits 0: check the CMD/entrypoint and logs, not the image build.
- Port-mapping confusion: -p host:container — on which side does the app listen?
- Layer cache mystery → --no-cache when source/behavior changed but tags didn't.
Interview checkpoint
Hands-on lab
- Write a multi-stage Dockerfile
- Build, tag, push, and pull an image
- Inspect layers and run with health constraints
Build, Multi-Stage, and Run an Image
40 min · beginner
Quick quiz
Which kernel features isolate containers?
What survives a container stop/remove by default?