Docker Fundamentals
Core concepts every container engineer should know cold.
How do containers differ from virtual machines?
A VM runs a full guest OS on a hypervisor with its own kernel, drivers, and userland - typically gigabytes in size and seconds to minutes to boot. A container is an isolated process (or process tree) on the host kernel, using namespaces for isolation and cgroups for resource limits. Containers start in milliseconds and share the host kernel, so they are lighter and faster but have a weaker security boundary than a separate kernel per VM.
What role do Linux namespaces and cgroups play in containers?
- Namespaces isolate what a process can see: PID (process IDs), NET (network stack), MNT (mount points), UTS (hostname), IPC (inter-process communication), and USER (UID/GID mappings). Together they create the illusion of a private environment.
- cgroups (control groups) limit and account for what a process can consume: CPU, memory, block I/O, and network bandwidth. Docker maps
--cpus,--memory, and related flags to cgroup settings.
Containers are not magic - they are standard Linux kernel features orchestrated by a runtime like containerd.
Describe Docker's client–server architecture.
The Docker client (docker CLI) sends REST API requests to the Docker daemon (dockerd), which runs on the host and manages images, containers, networks, and volumes. The daemon talks to containerd and runc to actually create and run containers. A registry (Docker Hub by default) stores and distributes images. On Linux the client typically connects via the Unix socket /var/run/docker.sock.
How are Docker images structured, and what are layers?
An image is a read-only stack of filesystem layers, each produced by a Dockerfile instruction (RUN, COPY, etc.). Layers are content-addressable and shared across images - if two images share a base layer, it is stored once on disk. When you run a container, Docker adds a thin writable container layer on top via a copy-on-write (CoW) filesystem (overlay2 on Linux). Deleting a container removes its writable layer; the image layers remain.
Walk through a well-structured Dockerfile for a production app.
- Start from a minimal, pinned base image (e.g.,
node:20-bookworm-slim). - Copy dependency manifests first, install deps, then copy source - maximizes layer cache hits.
- Use
.dockerignoreto excludenode_modules,.git, and build artifacts. - Run as a non-root
USERwhen possible. - Set
EXPOSEfor documentation; useHEALTHCHECKfor runtime probes. - Prefer
COPYoverADDunless you need tar extraction or remote URLs. - Use
CMDfor the default command andENTRYPOINTfor the fixed executable wrapper.
What is the difference between CMD and ENTRYPOINT?
ENTRYPOINT defines the main executable that always runs - it is the "what this container is." CMD supplies default arguments to that executable and is overridden easily at docker run time. A common pattern is ENTRYPOINT ["python", "app.py"] with CMD ["--port", "8080"]. If only CMD is set, passing arguments to docker run myimage --flag replaces the entire CMD rather than appending to it.
Which Docker CLI commands do you use most in day-to-day work?
docker build -t name:tag .- build an image from a Dockerfile.docker run -d --name app -p 8080:80 image:tag- start a detached container with port mapping.docker ps -a/docker logs -f container- inspect running state and stream logs.docker exec -it container sh- open a shell inside a running container for debugging.docker inspect- dump low-level JSON metadata (network, mounts, env).docker system df/docker image prune- reclaim disk from dangling images and stopped containers.
Explain the container lifecycle: create, start, stop, remove.
docker create allocates a container filesystem and config but does not start the process. docker start runs the main process. docker stop sends SIGTERM, waits for a grace period (default 10 s), then SIGKILL. docker rm deletes the container and its writable layer. docker run combines create + start. A stopped container retains its filesystem changes in the writable layer until removed.
How does Docker networking work? Compare bridge, host, and none.
- bridge (default): containers get a private network (
docker0bridge) with internal IPs. Port publishing (-p host:container) sets up iptables NAT rules so external traffic reaches the container. - host: the container shares the host's network namespace - no port mapping needed, but no network isolation.
- none: only a loopback interface; useful for batch jobs that need no network.
- Custom bridge networks: user-defined networks provide automatic DNS resolution between containers by service/container name.
What is the difference between a bind mount and a named volume?
A bind mount maps a specific host directory or file into the container (-v /host/path:/container/path). It is tied to the host filesystem layout and is common in local development. A named volume is managed by Docker under /var/lib/docker/volumes/, portable across hosts, and the recommended way to persist database data in production. Bind mounts can accidentally overwrite container paths; volumes are created and referenced by name, decoupling storage from host paths.
How do image tags and digests differ, and why does it matter?
A tag (e.g., nginx:1.25) is a mutable pointer - the same tag can be repushed with different content. A digest (e.g., nginx@sha256:abc123...) is an immutable content hash of the image manifest. In production, pin images by digest to guarantee reproducible deployments. Tags are convenient for humans; digests are the source of truth for supply-chain integrity.
What happens when you run docker pull and docker push?
docker pull contacts the registry, resolves the image manifest (by tag or digest), downloads each layer blob that is not already cached locally, and assembles the image in the local store. docker push uploads new layers the registry does not have, then updates the manifest and tag pointer. Because layers are content-addressed, unchanged layers are never re-uploaded - only new or modified layers transfer over the network.