# Interview Questions: Docker & Container Fundamentals

# Part 1 Questions: Container Model, Images & Runtime Lifecycle

## Conceptual

### 1. What is the practical difference between an image and a container?
An image is an immutable package of layers and runtime metadata. A container is a runnable instance of that image with a writable layer and runtime configuration such as ports, mounts, and environment variables.

### 2. What components does the Docker client-server model include?
The Docker CLI is a client that calls the Docker API. `dockerd` manages Docker objects and hands container creation to the runtime; registries store and distribute image content.

### 3. Why is a container not a virtual machine?
Containers are isolated processes that share the host kernel. VMs include a guest operating system and kernel, so their isolation and overhead model is different.

### 4. What happens to a container's writable layer when the container is removed?
It is removed with the container. Persisted data must live in a volume or external data service.

### 5. Why is an image tag not immutable release evidence?
A tag is a mutable pointer that can be repointed. A digest content-addresses one immutable image manifest and is the correct artifact identity for an audited deployment.

### 6. Why can docker exec be useful but dangerous as a fix?
It starts a diagnostic process in a running container, but interactive changes usually live only in the writable layer. The permanent correction belongs in the image or source-controlled runtime configuration.

### 7. What does containerd actually do, and why does a container survive a dockerd restart?
`containerd` manages image storage and container lifecycle beneath `dockerd`, delegating the actual process creation to `runc`. `runc` exits immediately after starting a container; a per-container `containerd-shim` process becomes the real parent of the container's process and stays running independently of both `dockerd` and `containerd`, which is why restarting the daemon doesn't kill already-running containers.

### 8. What are the two main pieces referenced by an OCI image manifest?
A config blob (JSON describing environment, entrypoint, and the layer digest chain) and an ordered list of layer blobs, each a compressed filesystem diff from the layer below it, including whiteout markers for deletions.

### 9. Why does copy-on-write storage make running many containers from the same image cheap?
Image layers are shared, read-only content stored once on disk regardless of how many containers use them. A container's first write to a file copies it up into that container's own writable layer; unmodified files are never duplicated.

### 10. What does `--init` actually fix?
It injects a minimal init process as PID 1, which execs the application as its child. This ensures zombie child processes get reaped and signals are forwarded correctly — responsibilities most application binaries don't implement themselves when running directly as PID 1.

### 11. Why is `docker commit` rarely the right tool for a real fix?
The resulting image has no Dockerfile, no build history, and can't be rebuilt or meaningfully code-reviewed — it captures whatever happened to be true about a container's filesystem at commit time, with no reproducible source.

### 12. What's the key difference between `docker save`/`load` and `docker export`/`import`?
`save`/`load` round-trip a real OCI image with full layer history and config metadata. `export`/`import` flatten a container's current filesystem into a single-layer tarball with no history, dropping the original entrypoint, environment, and other image config.

## Applied / Scenario

### 13. A container keeps restarting but users receive errors. What signals do you investigate?
Check application logs, exit codes, restart count, health endpoint behavior, and dependency errors. A restart policy proves only that Docker recreated a process, not that the service is ready or serving successful traffic.

### 14. How would you prove which image bytes are running after a security incident?
Record and inspect the immutable image digest, then compare it with the approved build and vulnerability evidence. Do not rely on a mutable tag such as `latest`.

### 15. A backing service is published with -p 5432:5432. What question should you ask?
Ask whether the database needs to be reachable outside the host. If it does not, bind it to loopback or avoid publishing it and use a private container network instead.

### 16. What is your first investigation sequence when docker run exits immediately?
Read `docker container logs`, inspect the exit code and configured command, then validate configuration, mounts, dependency reachability, and port conflicts. Avoid masking the failure with automatic restarts.

### 17. A container exits with code 137. What does that tell you before reading a single log line?
137 is 128 + 9 (`SIGKILL`), most commonly an OOM kill. Check `docker events --filter event=oom` and compare recent memory usage against the container's configured memory limit before assuming an application-level bug.

### 18. Two engineers pull the same tag and get different behavior, with no caching involved. What's a likely cross-architecture explanation?
The tag may resolve to a multi-platform manifest list with genuinely different per-architecture builds. `docker manifest inspect` reveals whether multiple platform-specific manifests exist; a bug present in only one architecture's build reproduces only on that architecture.

# Part 2 Questions: Dockerfiles, BuildKit & Image Delivery

## Conceptual

### 19. Why does instruction order in a Dockerfile affect build cache efficiency?
BuildKit's cache is layer-keyed: a layer's cache key depends on the instruction and the content it reads. Copying dependency manifests and installing dependencies before copying application source means a source-only change doesn't invalidate the expensive dependency-install layer.

### 20. What problem does a multi-stage Dockerfile solve that a single-stage build doesn't?
It keeps build tooling (compilers, SDKs, full dependency trees) out of the final runtime image by copying only the finished artifact across a stage boundary, reducing both image size and attack surface.

### 21. Why should a credential never be passed via ARG or ENV?
Both are recorded in image layer history and remain inspectable via `docker history`, even if a later instruction removes the resulting file — layer history is additive, not destructive. A `--mount=type=secret` mount is the only option that never writes the credential into any layer.

### 22. What's the practical difference between an SBOM and a provenance attestation?
An SBOM lists the software components inside an image; a provenance attestation records how the image was built (the Dockerfile, build arguments, and builder identity). One answers "what's inside," the other answers "how and from what source."

### 23. Why is promoting a release by re-tagging a verified digest safer than rebuilding for the release tag?
Floating base image tags, package mirrors, or non-deterministic build steps can produce a different digest on a second build even from the same Dockerfile. Re-tagging with `docker buildx imagetools create` guarantees the artifact that passed staging is bit-for-bit what reaches production.

## Applied / Scenario

### 24. CI cache hit rate is near zero despite correct instruction ordering. What's the likely cause?
Each CI job likely runs on a fresh, ephemeral runner with no local BuildKit cache. Correct ordering only helps within one build; across separate runners it does nothing without an explicit shared cache via `--cache-from`/`--cache-to type=registry` or an equivalent CI-native backend.

### 25. A production image's `docker history` reveals a plaintext token from an ARG passed several stages earlier. What went wrong, and what's the fix?
A later `RUN rm` removed the file from the final filesystem but not from the layer history that contained it — every image built with that Dockerfile carries the leaked credential. The token must be rotated, and future builds must use `--mount=type=secret` instead of ARG/ENV for any credential.

### 26. A multi-stage build's final image is much larger than expected. How do you investigate?
Run `docker history --no-trunc` to see each layer's size and origin, and confirm the final stage is actually a minimal runtime base rather than accidentally reusing a build stage. Check that `COPY --from=<stage>` copies only the specific artifact needed, not an entire directory still containing build tooling.

### 27. A compliance review needs to know whether a CVE-affected library shipped in a four-month-old production image, without pulling it. How do you answer?
If the image was built with `--sbom=true`, query its stored SBOM attestation directly by digest with `docker buildx imagetools inspect --format '{{json .SBOM}}'` and search it for the library and version — no pull or re-scan required.

### 28. A team wants to switch a service to a distroless base image, but their runbook relies on `docker exec ... sh` for live diagnosis. How do you reconcile this?
Recognize the missing shell is a deliberate security property, not an oversight. Replace shell-based diagnosis with structured logging, `docker inspect`/`stats`, or a namespace-sharing debug sidecar (`--network container:<target>`), rather than reintroducing a shell into the production image.

# Part 3 Questions: Networking, Storage & Docker Compose

## Conceptual

### 29. Why can't two containers on Docker's default bridge network reach each other by name?
The default bridge has no embedded DNS server. Only user-defined bridge networks include the automatic resolver (listening at 127.0.0.11) that maps container and service names to their current IP.

### 30. What's the difference between `depends_on` with no condition and `depends_on: condition: service_healthy`?
Without a condition, `depends_on` only waits for the dependency's container to start, not for the service inside it to be ready. `service_healthy` waits for the dependency's own `HEALTHCHECK` to pass first.

### 31. Why is a bind mount not equivalent to a named volume for production durability?
A bind mount's durability depends entirely on that exact host path continuing to exist on whatever host next runs the container. A named volume is Docker-managed and doesn't assume a specific host path is present after redeployment to a different host.

### 32. What's the difference between `deploy.resources.limits` and `deploy.replicas` in a Compose file?
`resources.limits`/`reservations` are honored by plain `docker compose up`. Fields like `replicas` and `placement` are Swarm-mode only and are silently ignored outside Swarm.

### 33. When should you reach for `docker compose run` instead of `docker compose exec`?
`run` starts a fresh, isolated container from the current image and configuration — correct for a one-off task like a migration that shouldn't depend on whatever code version happens to be currently live. `exec` runs inside the already-running container, which may be a stale version.

## Applied / Scenario

### 34. Two Compose services in the same file can't reach each other despite no custom `networks:` section. What's the first thing to check?
Confirm both containers belong to the same Compose project — a second, independently started project (different `-p` name, or a separate directory) creates its own default network, and two projects' networks are not shared even with similar service names.

### 35. A production Redis container was published with a bare `-p 6379:6379` "for debugging" and never reverted. What's the risk?
A bare port publish with no host IP binds to every host interface, not just the host itself — an unauthenticated Redis instance believed to be reachable "only from the application" becomes reachable from anywhere the host's network is exposed to.

### 36. An integration-test CI job using `docker compose up -d --wait` intermittently times out, though the same stack starts reliably locally. What should you check first?
Compare the CI runner's resource allocation against a developer machine — a health check's `start_period`/`retries` tuned against local startup times can be too tight for a slower or contended CI runner. Widen those values for CI via an override file before assuming the health check logic itself is wrong.

### 37. A `docker compose down` accidentally deleted a named volume with real data. What happened, and how is this prevented?
A bare `docker compose down` preserves named volumes; `--volumes`/`-v` explicitly removes them. Prevention is procedural: never include `--volumes` in a script or alias used against an environment with real data, and use a separately, clearly named script for the intentional wipe case.

### 38. A reverse proxy needs to reach both a web tier and an API tier, but the API's database must stay unreachable from the proxy even if it's compromised. How do you express this with Compose networking alone?
Attach the proxy and API to a shared network, and attach the database only to a separate network the proxy never joins. The API bridges both networks; the proxy has no route to the database network at all, enforced at the network layer independent of any application-level auth.

# Part 4 Questions: Operating Containers Safely & the Kubernetes Handoff

## Conceptual

### 39. What's the difference between what capabilities, seccomp, and AppArmor each restrict?
Capabilities control which privileged operations are available at all. Seccomp filters which syscalls can be invoked. AppArmor/SELinux enforce mandatory access control over filesystem paths, network operations, and capability use — all three are complementary, not substitutes for each other.

### 40. What does rootless Docker actually change compared to the traditional daemon model?
It runs `dockerd` itself under an unprivileged user via Linux user namespaces, so a container escape lands the attacker as that unprivileged user rather than as full host root. It doesn't replace container-level controls like capability drops or read-only filesystems.

### 41. Why should a health check's liveness and readiness responsibilities be separated?
An overly broad check (one that tests an expensive downstream dependency) can turn a transient issue into a mass restart event across every replica simultaneously. Liveness should stay cheap and dependency-free; readiness should test the specific dependencies request handling actually needs.

### 42. Why does an entrypoint written as `CMD ["sh", "-c", "node server.js"]` often break graceful shutdown?
The shell, not the application, becomes PID 1 and may not forward `SIGTERM` to the child process. Using exec form or an explicit `exec` in the entrypoint script ensures the application itself receives the signal.

### 43. What's the actual difference between container orchestration and container scheduling?
Scheduling is the narrower concern of deciding which node a workload runs on. Orchestration is broader — scheduling plus health-driven rescheduling, rolling updates, service discovery, and continuous reconciliation of actual state toward desired state.

## Applied / Scenario

### 44. A container's health check passes, but users report the service is unresponsive. What are the first two things to check?
First, confirm what the check actually tests — a trivial liveness-only check can pass while the real request path is broken. Second, check for resource pressure (CPU throttling, memory near its limit, PID count) that could make the process technically alive but too starved to serve requests in time.

### 45. A team says `--user` broke their app on startup and reverted to running as root. What's the more likely root cause, and the correct fix?
Most likely a file or directory the non-root user can't write to or read, often still owned by root from the image build. Fix ownership at the source with `COPY --chown` or a correctly-owned mount, rather than reverting to root to avoid diagnosing the specific permission error.

### 46. A host running several internal teams' services is questioned for multi-tenancy risk. What isolation do per-container resource limits and separate networks actually provide, and what do they not provide?
They prevent noisy-neighbor resource contention and network-layer reachability between tenants. They do not protect against a kernel-level compromise, since all containers still share the same host kernel and daemon — that requires an explicit decision about whether the host is an acceptable shared trust boundary.

### 47. A team wants to migrate to Kubernetes primarily because releases cause a few seconds of downtime. Is that alone sufficient justification, and what smaller fix is worth trying first?
It's a valid signal, but running multiple replicas behind a reverse proxy that only routes to ready replicas can eliminate deploy-time downtime on a single host without a full multi-host orchestrator. Kubernetes is justified independently if the team also needs resilience against a whole-host failure — worth confirming which motivation is actually driving the request.

### 48. An automated image-watcher redeploys any container whose tag gets a new digest. What does this bypass, and what should replace it?
It bypasses every verification gate — scanning, staging validation, signing — that a build pipeline exists to enforce, deploying whatever was merely pushed rather than what was verified. Route all deployments through the same pipeline that promotes a verified digest instead of an unconditional tag-watcher.

## Quick-Fire Recall

| Term | One-line answer |
|---|---|
| `dockerd` | Privileged Docker Engine daemon that manages Docker objects. |
| `containerd` | Daemon beneath `dockerd` managing image storage and container lifecycle. |
| `containerd-shim` | Per-container parent process that keeps a container alive across a daemon restart. |
| `runc` | Low-level OCI runtime that creates namespaces/cgroups and starts the container process, then exits. |
| Image layer | Immutable filesystem change used to compose an image. |
| Container writable layer | Ephemeral runtime filesystem changes for one container, via copy-on-write. |
| OCI image manifest | JSON document referencing a config blob and an ordered list of layer blobs. |
| Registry | Service that stores and distributes image repositories. |
| Tag | Mutable human-readable image reference. |
| Digest | Immutable content-addressed image identifier. |
| Manifest list / image index | A manifest referencing multiple platform-specific manifests under one tag. |
| Namespace | Kernel isolation mechanism that constrains a process view (PID, mount, net, UTS, IPC, user). |
| Cgroup | Kernel resource accounting and limiting mechanism. |
| `docker commit` | Snapshots a container's filesystem into an image with no Dockerfile or build history — rarely the right tool. |
| BuildKit cache mount | A persistent, cumulative scratch directory for a package manager's cache, never written to a layer. |
| Multi-stage build | A Dockerfile pattern that discards build tooling and ships only the finished artifact. |
| SBOM | Inventory of the software components inside an image. |
| Provenance attestation | Record of how and from what source an image was built. |
| `--cap-drop ALL` | The recommended default posture: deny every capability, add back only what's demonstrably needed. |
| Seccomp | Kernel syscall filter restricting which syscalls a process may invoke. |
| Rootless Docker | Runs the daemon itself under an unprivileged user via user namespaces. |
| User-defined bridge network | A Docker network with embedded DNS-based service discovery by container/service name. |
| `service_healthy` | A Compose `depends_on` condition that waits for a dependency's health check, not just its startup. |
| Named volume | Docker-managed persistent storage, independent of any specific host path. |
| Liveness vs. readiness | Liveness = can the process respond at all; readiness = can it currently serve real traffic. |
| `--init` | Injects a minimal init process as PID 1 to reap zombies and forward signals correctly. |
