Interview Q&A · 38 questions · 18 answered publicly
Docker Interview Questions
Ordered by how often they're asked. Sign in free to see every answer, rate your confidence and run timed mock interviews.
-
Most asked What is a container, and how does it differ from a virtual machine?
Summary
A container is an isolated process (or group of processes) on the host's Linux kernel, isolated with namespaces (what it can see: processes, network, mounts, users) and limited with cgroups (how much CPU, memory and I/O it may use), running from an image's filesystem. A virtual machine runs a full guest operating system with its own kernel on a hypervisor.
Longer Answer
Containers start in milliseconds, use little overhead and pack densely, but share the host kernel, so isolation is weaker than a VM's: a kernel vulnerability can affect every container on the host. VMs give stronger isolation and can run different kernels or operating systems. Many platforms combine them: containers inside VMs, or micro-VMs per container (Firecracker in AWS Fargate and Lambda, Kata Containers) for stronger isolation.
On macOS and Windows, Docker Desktop runs containers inside a lightweight Linux VM.
Key Points
- Namespaces isolate; cgroups limit.
- Shared host kernel.
- Fast and light, weaker isolation than VMs.
- Micro-VMs for stronger isolation.
-
Most asked What is the difference between an image and a container, and how do image layers work?
Summary
An image is a read-only template: an ordered stack of filesystem layers plus metadata (entrypoint, environment, exposed ports). A container is a running (or stopped) instance of an image with a thin writable layer on top. Layers are content-addressed and shared between images, so pulling and storing many images that share a base is efficient.
Longer Answer
Each filesystem-changing Dockerfile instruction (
RUN,COPY,ADD) creates a layer. The storage driver (overlay2 on most Linux hosts) presents the layers as one filesystem using a union mount; changes made by the container go to its writable layer with copy-on-write and disappear when the container is removed (persistent data belongs in volumes).Because layers are immutable, deleting a file in a later layer does not shrink the image: the bytes remain in the earlier layer. That is why cleanup must happen in the same
RUNinstruction that created the files, or in a multi-stage build.Key Points
- Image = read-only layers + metadata.
- Container = image + writable layer.
- Layers shared and content-addressed.
- Deleting in a later layer does not shrink the image.
-
Most asked How does Docker build caching work, and how do you order a Dockerfile to use it well?
Summary
Each instruction's result is cached; on rebuild, Docker reuses cached layers until it reaches an instruction whose inputs changed (the instruction text, or for
COPY/ADDthe checksums of copied files), and every instruction after that is rebuilt. So put rarely changing steps first and frequently changing ones (copying source code) last.Longer Answer
Classic pattern: copy only the dependency manifests, install dependencies, then copy the rest of the source. Code edits then reuse the cached dependency layer.
FROM node:22-slim WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --omit=dev COPY . . CMD ["node", "server.js"]BuildKit adds cache mounts (
RUN --mount=type=cache,target=/root/.npm npm ci) that keep package-manager caches between builds, and remote cache export/import (--cache-to,--cache-from) so CI runners share caches. A.dockerignorekeeps irrelevant files (.git,node_modules, logs) from invalidatingCOPY . ..Key Points
- Cache reused until the first changed instruction.
- Dependencies before source code.
- .dockerignore to avoid needless invalidation.
- BuildKit cache mounts and remote caches.
-
Most asked What are multi-stage builds, and why use them?
Summary
A multi-stage Dockerfile has several
FROMstages: build tools and dependencies live in earlier stages, and the final stage copies only the built artifacts (COPY --from=build ...) into a small runtime image. The final image excludes compilers, source code, dev dependencies and build secrets.Longer Answer
FROM golang:1.23 AS build WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app FROM gcr.io/distroless/static-debian12:nonroot COPY --from=build /out/app /app ENTRYPOINT ["/app"]Benefits: much smaller images (faster pulls, faster scaling), smaller attack surface, and one Dockerfile for both build and runtime. Stages can also be targeted for tests (
docker build --target test).Key Points
- Build in one stage, ship from another.
- No compilers or dev dependencies in the final image.
- Smaller and more secure.
- Target stages for tests.
-
Most asked CMD or ENTRYPOINT: what is the difference, and what are exec and shell forms?
Summary
ENTRYPOINTsets the executable the container runs;CMDprovides default arguments (or a default command if there is no entrypoint), whichdocker run image argsoverrides. The exec form (["node", "server.js"]) runs the process directly; the shell form (node server.js) wraps it in/bin/sh -c.Longer Answer
Prefer the exec form: with the shell form, the shell becomes PID 1 and typically does not forward signals, so
docker stop(SIGTERM) does not reach your application, which is killed after the timeout instead of shutting down gracefully. A common pattern is anENTRYPOINTscript that prepares the environment and ends withexec "$@"so the real process replaces the shell, plusCMDfor default arguments.Key Points
- ENTRYPOINT = executable; CMD = default args.
- Exec form runs the process directly.
- Shell form breaks signal handling.
- Entrypoint scripts end with exec "$@".
-
Most asked What are Dockerfile best practices for production images?
Summary
Use a small, trusted, pinned base image; use multi-stage builds; order instructions for caching; combine package installs with cleanup in one layer; use a
.dockerignore; run as a non-root user; use exec-form entrypoints; add a health check where the platform uses it; never bake secrets into images; and label images with source and version metadata.Longer Answer
More details:
- Pin base images by version, and in high-security setups by digest (
python:3.12-slim@sha256:...), and rebuild regularly to pick up patches. apt-get update && apt-get install -y --no-install-recommends ... && rm -rf /var/lib/apt/lists/*in a singleRUN.COPYrather thanADDunless you need its extras.USER 10001(and files owned appropriately) so a container escape starts unprivileged.- One process per container; configuration from environment variables.
- Lint with hadolint and scan with Trivy or Docker Scout in CI.
Key Points
- Small pinned base; multi-stage.
- Cache-friendly order; single-layer cleanup.
- Non-root; exec form; no secrets.
- Lint and scan in CI.
- Pin base images by version, and in high-security setups by digest (
-
Most asked ARG or ENV: what is the difference, and how do you pass secrets into a build safely?
Summary
ARGdefines build-time variables available only while building (set with--build-arg);ENVsets environment variables persisted in the image and present at runtime. Neither is safe for secrets: build args can appear in image history and metadata, andENVvalues are stored in the image.Longer Answer
Use BuildKit secret mounts:
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci, passed withdocker build --secret id=npmrc,src=$HOME/.npmrc. The secret is available only during thatRUNstep and never written to a layer. For SSH access to private repositories, use--mount=type=ssh. Runtime secrets belong in the orchestrator's secret mechanism, not the image.Code Example
# syntax=docker/dockerfile:1 RUN --mount=type=secret,id=npm_token \ NPM_TOKEN=$(cat /run/secrets/npm_token) npm ciKey Points
- ARG: build-time; ENV: persisted runtime.
- Neither is safe for secrets.
- BuildKit --mount=type=secret.
- Runtime secrets from the orchestrator.
-
Most asked How do you secure Docker containers and images?
Summary
Use minimal, regularly rebuilt base images from trusted sources; scan images for vulnerabilities in CI and registries; sign images and verify signatures; run as non-root; drop capabilities (
--cap-drop ALL); use a read-only root filesystem; set resource limits; never mount the Docker socket into containers; and keep secrets out of images.Longer Answer
Additional measures: keep Docker Engine and the host kernel patched; use rootless Docker or user namespaces to reduce the impact of escapes; apply the default seccomp and AppArmor/SELinux profiles (never
--privilegedunless unavoidable); generate SBOMs; and restrict who can access the Docker daemon, because access to it (or its socket) is effectively root on the host.Key Points
- Minimal trusted images; scan and sign.
- Non-root, drop capabilities, read-only FS.
- Never mount docker.sock; no --privileged.
- Daemon access = root.
-
Most asked Why does PID 1 matter in containers, and what problems can it cause?
Summary
The container's main process runs as PID 1, which Linux treats specially: it does not get default signal handlers (signals it does not handle are ignored, so SIGTERM may do nothing), and it is responsible for reaping orphaned child processes, which otherwise become zombies.
Longer Answer
Symptoms: containers take the full stop timeout (10 s in Docker, 30 s grace period in Kubernetes) to stop and are then killed, losing in-flight work; zombie processes accumulate when the app spawns children. Fixes: handle SIGTERM in the application, use the exec form, and run a tiny init when needed (
docker run --init, which uses tini, or tini/dumb-init as the entrypoint).Key Points
- PID 1 lacks default signal handlers.
- Must reap zombie processes.
- Handle SIGTERM; exec form.
- --init / tini for reaping and forwarding.
-
Most asked How do you make Docker images smaller?
Summary
Start from a minimal base (slim, Alpine, distroless or
scratchfor static binaries), use multi-stage builds to leave build tools behind, install only runtime dependencies (--no-install-recommends, production-only packages), clean caches in the same layer, exclude unneeded files with.dockerignore, and inspect layers to find what is large.Longer Answer
Tools:
docker image historyanddiveshow what each layer adds. Alpine uses musl libc, which can cause subtle differences or slow builds for languages with native extensions (Python wheels often target glibc), so-slimDebian-based images are a safer default for many stacks; distroless images contain only the runtime and no shell, which also reduces attack surface (debug with ephemeral debug containers).Smaller images pull faster, which directly speeds up autoscaling and deploys, and have fewer packages to patch.
Key Points
- Minimal bases; multi-stage.
- Runtime dependencies only; same-layer cleanup.
- dive / history to inspect.
- Alpine musl caveats; distroless has no shell.
-
Most asked Volumes, bind mounts and tmpfs: when do you use each?
Summary
Named volumes are managed by Docker and are the right choice for persistent container data (databases in development, uploaded files); bind mounts map a host path into the container, ideal for development (live-editing source code) or specific host files; tmpfs mounts keep data in memory only, for temporary or sensitive data.
Longer Answer
Data in a container's writable layer disappears with the container and is slower (copy-on-write), so anything that must persist goes in a volume. Bind mounts depend on the host's directory layout and permissions (UID mismatches between host and container are a common annoyance) and can expose host files, so avoid them in production. In orchestrators, persistent storage is provided by the platform (Kubernetes PersistentVolumes, EFS for ECS).
Key Points
- Volumes: persistent, Docker-managed.
- Bind mounts: dev and host files.
- tmpfs: memory only.
- Writable layer is ephemeral.
-
Most asked How does Docker networking work? Explain bridge, host and user-defined networks.
Summary
By default containers attach to a bridge network with private IPs and reach the outside world through NAT;
-p 8080:80publishes a container port on the host. User-defined bridge networks add automatic DNS, so containers resolve each other by name, and better isolation.--network hostshares the host's network stack (no isolation, no port mapping). Overlay networks span multiple hosts (Swarm).Longer Answer
Containers on the default bridge cannot resolve each other by name, which is why Docker Compose creates a user-defined network per project where services reach each other as
http://api:8000. Inside a container,localhostis the container itself, not the host or another container, a frequent beginner mistake; use the service name, orhost.docker.internal(Docker Desktop, or with--add-host) to reach the host. Publishing ports binds to all interfaces by default (0.0.0.0), so bind to127.0.0.1:for local-only access.Key Points
- Bridge + NAT; -p publishes ports.
- User-defined networks provide DNS.
- Host network shares the host stack.
- localhost inside a container is the container.
-
Most asked What is Docker Compose used for, and how do you handle service start-up order?
Summary
Compose defines multi-container applications in a YAML file (
compose.yaml): services, images or builds, ports, volumes, networks, environment and dependencies, and starts them together withdocker compose up. It is the standard tool for local development environments and simple single-host deployments.Longer Answer
depends_oncontrols start order, but by default only waits for containers to start, not for the service inside to be ready. Usedepends_onwithcondition: service_healthyplus ahealthcheckon the dependency (for examplepg_isreadyfor PostgreSQL), and still make applications retry connections, because dependencies can restart later too.Other useful features: profiles for optional services,
env_file, override files for per-developer settings,watchfor syncing code changes, andincludeto combine projects.Code Example
services: db: image: postgres:17 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s retries: 10 api: build: . depends_on: db: condition: service_healthyKey Points
- Multi-container apps in YAML.
- Great for local development.
- depends_on + service_healthy + healthcheck.
- Apps must still retry connections.
-
Most asked How do you limit a container's CPU and memory, and what happens when it exceeds them?
Summary
Use
--memory(and optionally--memory-swap) and--cpus(or CPU shares) withdocker run, ordeploy.resources.limitsin Compose. When a container exceeds its memory limit, the kernel's OOM killer kills a process inside it (the container usually exits with code 137); exceeding the CPU limit causes throttling, not killing.Longer Answer
Runtimes inside containers must respect the limits: modern JVMs (container-aware since Java 10, backported to 8u191), Node.js and Go read cgroup limits, but explicit tuning (
-XX:MaxRAMPercentage,--max-old-space-size) is still common. Without limits, one container can starve everything else on the host.docker statsshows live usage.Key Points
- --memory and --cpus.
- Memory over limit: OOM kill (137).
- CPU over limit: throttling.
- Make runtimes respect cgroup limits.
-
Most asked How should you tag Docker images, and why is 'latest' a problem?
Summary
Tag images with immutable, traceable identifiers such as the Git commit SHA (and optionally a semantic version), and deploy by those tags or by digest.
latestis just a default tag name, not 'the newest version': it moves, so different hosts can run different code under the same tag, rollbacks are unclear, and caches may serve stale images.Longer Answer
Good practice:
org/app:1.4.2plusorg/app:git-3f9c2ab; enable tag immutability in the registry (ECR, Artifact Registry) so a tag can never be overwritten; deploy by digest (@sha256:...) for full reproducibility; and uselatest(if at all) only for local convenience. Record which tag runs in each environment for audits and rollbacks.Key Points
- Immutable tags: commit SHA, semver.
- 'latest' moves and is ambiguous.
- Registry tag immutability.
- Deploy by digest for reproducibility.
-
Most asked How do you debug a container that exits immediately or behaves differently in production?
Summary
Check the exit code and logs (
docker ps -a,docker logs <id>,docker inspectfor state and OOMKilled), run it interactively with an overridden entrypoint (docker run -it --entrypoint sh image), and compare its environment, configuration, mounts, user and architecture with what you expect.Longer Answer
Frequent causes: the main process runs in the background and the container exits (the main process must stay in the foreground); missing environment variables or config files; file permissions when running as non-root; wrong CPU architecture (
exec format errorwhen an arm64 image runs on amd64); andlocalhostassumptions. For running containers,docker exec -it <id> sh(ordocker debugfor images without a shell) lets you inspect from inside.Key Points
- Exit code, logs, inspect.
- Override entrypoint to explore.
- Foreground process; env; permissions; arch.
- exec or docker debug into running containers.
-
Most asked How do you run Docker builds in CI pipelines efficiently and safely?
Summary
Use BuildKit with remote caching (registry or CI cache) so ephemeral runners reuse layers, build once and push an immutable tag, scan the image, sign it, and deploy that exact digest to every environment. Avoid privileged Docker-in-Docker on shared runners where possible; use rootless or remote builders.
Longer Answer
Pipeline sketch: build with
--cache-from/--cache-to, run tests against the built image, scan (Trivy, Grype, Docker Scout) and fail on critical vulnerabilities with an exception process, generate an SBOM and provenance attestations, sign (cosign), push with the commit SHA tag, and promote the same digest through environments. Authenticate to registries with OIDC or short-lived tokens, not stored passwords.Key Points
- Remote build caches.
- Build once, promote the same digest.
- Scan, SBOM, sign.
- Avoid privileged DinD; OIDC to registries.
-
Most asked What is a software supply chain attack on containers, and how do you defend against it?
Summary
An attacker compromises something you build from rather than your code directly: a malicious or typo-squatted base image, a compromised dependency, a tampered CI pipeline, or a pushed image replaced in a registry. Defences: trusted, pinned sources; vulnerability and malware scanning; signed images with signature verification before deploy; SBOMs and provenance attestations; and locked-down CI and registries.
Longer Answer
Frameworks such as SLSA describe levels of build integrity. Practical steps: use official or verified-publisher images and internal mirrors; pin by digest; generate provenance with BuildKit (
--provenance,--sbom); sign with Sigstore cosign; verify signatures at admission in Kubernetes (Kyverno, policy-controller); enable registry tag immutability; and require least-privilege, short-lived credentials in CI.Key Points
- Attacks via bases, dependencies, CI, registries.
- Pin, scan, sign, verify.
- SBOM and provenance (SLSA).
- Locked-down CI and registries.
- Why is mounting the Docker socket into a container dangerous?
- What is BuildKit, and what does docker buildx add?
- COPY or ADD: what is the difference?
- What does HEALTHCHECK do in a Dockerfile, and do orchestrators use it?
- How do container logs work in Docker, and how do you stop them filling the disk?
- What is the OCI, and how do Docker, containerd, runc and Podman relate?
- What should you consider when choosing a base image?
- How do you handle configuration for containers across environments?
- What is the Docker build context, and why does it matter?
- Why might a container work on your laptop but fail on a server or in CI?
- How do you run a database in Docker for local development, and should you do it in production?
- How do you speed up a slow Docker build?
- Explain what happens when you run docker run nginx.
- What is Docker Swarm, and why do most teams use Kubernetes or managed services instead?
- What are rootless Docker and user namespaces?
- How do you clean up disk space used by Docker?
- How do you run multiple processes in one container, and should you?
- What changed with Docker Desktop licensing, and what are the alternatives?
- How do you handle time zones, locales and certificates in minimal images?
- Docker Compose in production: is it appropriate?