← All interview questions

Top Docker Interview Questions & Answers

Docker questions are common across almost every backend and DevOps interview, testing your grasp of containers vs. VMs and how images/containers actually work.

Take Practice Interview now
Speak your answers out loud and get a scored report in minutes — free trial included.
Start Free →

1. What is the difference between a container and a virtual machine?

A VM virtualizes an entire machine, including its own OS kernel, running on top of a hypervisor — heavier in resource usage and slower to start. A container virtualizes at the OS level, sharing the host's kernel while isolating processes, filesystem, and network via namespaces and cgroups — this makes containers far lighter and faster to start (seconds vs. minutes) but means containers on the same host share a kernel, unlike VMs.

2. What is the difference between a Docker image and a container?

An image is a read-only, immutable template — a packaged filesystem plus metadata (built from a Dockerfile) that defines an application and its dependencies. A container is a running (or stopped) instance of an image, with its own writable layer on top for runtime changes. You can run multiple independent containers from the same image, each isolated from the others.

3. What are Docker layers, and why does layer caching matter for build speed?

Each instruction in a Dockerfile (FROM, RUN, COPY, etc.) creates a new immutable layer stacked on the previous one, and Docker caches each layer. If a layer's inputs haven't changed since the last build, Docker reuses the cached layer instead of rebuilding it. This is why Dockerfiles are typically ordered to put rarely-changing instructions (like installing dependencies) before frequently-changing ones (like copying application source code) — so code changes don't invalidate the expensive dependency-install layer.

4. What is a multi-stage build and why use one?

A multi-stage build uses multiple FROM statements in one Dockerfile, where an early stage can include build tools/compilers to produce compiled artifacts, and a later, final stage copies only those artifacts into a minimal base image. This keeps the final production image small and free of build-time dependencies (compilers, dev tools) that aren't needed at runtime, reducing image size and attack surface.

5. How does Docker networking work by default?

By default, Docker creates a bridge network on the host, and containers attached to it get their own internal IP and can communicate with each other by container name (via Docker's embedded DNS) if on the same user-defined bridge network. Ports must be explicitly published (-p host:container) to be reachable from outside the host, since containers aren't exposed to the outside world by default.

6. What is a Docker volume, and why not just store data in the container's filesystem?

A container's writable layer is ephemeral — deleting the container deletes any data written to it. Volumes are storage managed by Docker (or bind mounts to a host path) that exist independently of any single container's lifecycle, so data persists across container restarts/recreation and can be shared between multiple containers, which is essential for stateful workloads like databases.

7. What's the difference between CMD and ENTRYPOINT in a Dockerfile?

ENTRYPOINT defines the fixed executable that always runs when the container starts. CMD provides default arguments to that entrypoint (or the default command if no ENTRYPOINT is set), which can be overridden at docker run time by appending arguments. Combining both (ENTRYPOINT for the binary, CMD for default flags) is a common pattern that lets users override just the arguments without needing to override the whole command.

8. What is Docker Compose and when would you use it?

Docker Compose is a tool for defining and running multi-container applications using a single YAML file (typically docker-compose.yml) that describes each service, its image or build context, networking, volumes, and environment variables. Instead of running a series of long docker run commands, you declare the desired state once and bring the whole stack up with docker compose up and tear it down with docker compose down. Compose automatically creates a shared user-defined network for the services, so they can reach each other by service name out of the box. It's commonly used for local development and testing environments where you need several interdependent services, like a web app, a database, and a cache, running together.

9. What is a .dockerignore file and why is it important?

A .dockerignore file lists paths and patterns that should be excluded when Docker sends the build context to the daemon, similar in syntax to .gitignore. Without it, files like .git directories, local node_modules, log files, or secrets can get sent along with the build context, which slows down builds and can bloat or even leak sensitive data into image layers via COPY/ADD instructions. Keeping the build context lean also means Docker has less data to transfer to the daemon, which matters a lot when building against a remote Docker host. It's considered a best practice on virtually every real-world Dockerfile.

10. How should you approach image tagging and versioning?

Relying only on the latest tag is risky because it's mutable and gives no guarantee about what's actually running — two people pulling latest at different times can get different images. Best practice is to tag images with something immutable and traceable, like a semantic version (1.4.2), a git commit SHA, or a build number, so you can always trace a running container back to the exact source that produced it. Many teams also tag with both a specific version and a rolling alias (e.g., 1.4 and 1.4.2) to support different levels of pinning. Combined with a registry, this makes rollbacks straightforward since you can just redeploy a previous, known-good tag.

11. What's the difference between docker exec and docker attach?

docker attach connects your terminal to the container's main process (PID 1) and its existing stdin/stdout/stderr streams — you're essentially plugging into the same session the container was started with, so exiting can potentially stop the container if you send the wrong signal. docker exec instead starts a brand-new process inside the already-running container's namespaces, most commonly used as docker exec -it <container> bash to get an interactive shell for debugging. Because exec spawns a separate process, exiting that shell doesn't affect the container's main process at all. In practice, exec is the far more common and safer tool for poking around inside a running container.

12. What are Docker health checks and why do they matter?

A HEALTHCHECK instruction in a Dockerfile (or the equivalent option in Compose) defines a command Docker runs periodically inside the container to determine whether the application is actually functioning, not just whether the process is alive. Based on the exit code, Docker reports the container's status as healthy, unhealthy, or starting, which you can see in docker ps. This matters because a container can have its main process still running while the application inside is deadlocked, unable to reach a dependency, or otherwise broken — a health check catches that. Orchestrators like Docker Swarm or Kubernetes (via similar liveness/readiness probes) use this status to decide whether to route traffic to a container or restart it.

13. How do you reduce Docker image size?

The biggest lever is choosing a smaller base image — swapping a full Debian or Ubuntu base for a slim or alpine variant (or distroless) can cut hundreds of megabytes right away, though Alpine's use of musl instead of glibc occasionally causes compatibility issues worth testing for. Combining related RUN commands with && and cleaning up package manager caches in the same layer (e.g., apt-get install && rm -rf /var/lib/apt/lists/*) prevents temporary files from bloating a layer that can never be undone later. Multi-stage builds help enormously by discarding compilers and build-time dependencies from the final image. Finally, using a .dockerignore file and only copying what's actually needed avoids pulling unnecessary files into the image.

14. How do you pass environment variables into a container?

You can set environment variables at runtime with docker run -e KEY=value or --env-file to load many at once from a file, or declare defaults in the Dockerfile with the ENV instruction, which get baked into the image. Compose files let you specify them per-service under environment or reference an external .env file. Runtime-supplied variables (via -e or Compose) take precedence over ENV defaults set at build time, which is what makes it possible to use the same image across dev, staging, and production with different configuration. Sensitive values like passwords or API keys shouldn't be hardcoded via ENV in the Dockerfile since they'd be baked into the image and visible in its history — those are better injected at runtime or via a secrets manager.

15. What is Docker's copy-on-write filesystem and why does it matter?

Docker images are made up of stacked, read-only layers, and when a container runs, Docker adds a thin writable layer on top using a copy-on-write (CoW) strategy, typically via a storage driver like overlay2. When a process in the container modifies a file that exists in a lower read-only layer, the storage driver copies that file up into the writable layer first and then applies the change there, leaving the original image layers untouched. This is what allows many containers to share the same underlying image layers on disk without duplicating storage, since only the diffs unique to each container get written. It also explains why writes inside a container disappear when the container is removed — they only ever lived in that container's own writable layer.

16. What are Docker restart policies?

A restart policy tells the Docker daemon whether and how to automatically restart a container if it stops, which you set with --restart on docker run or under restart in Compose. The options are no (default, never restart), on-failure[:max-retries] (restart only if it exits with a non-zero code, optionally capped at a retry count), always (always restart regardless of exit code, including after a daemon restart), and unless-stopped (like always, but won't restart if the container was manually stopped before the daemon restarted). Choosing the right policy matters for production services — unless-stopped or always is common for long-running services you want to survive host reboots, while on-failure is useful for jobs where a clean exit should stay stopped.

17. What's the difference between COPY and ADD in a Dockerfile?

Both instructions copy files from the build context into the image, but ADD has two extra behaviors: it can automatically extract local tar archives into the destination, and it can fetch a file from a remote URL directly. COPY does neither of those — it's a straightforward, predictable file copy and nothing more. Docker's own best practice is to default to COPY unless you specifically need ADD's tar-extraction behavior, because ADD's implicit magic (especially the URL-fetching, which doesn't clean up afterward or verify content) makes builds less transparent and harder to reason about.

18. How do you limit the CPU and memory a container can use?

You can cap resources at docker run time with flags like --memory (e.g., --memory=512m) to set a hard memory ceiling, and --cpus (e.g., --cpus=1.5) to limit how much CPU time the container can consume, both enforced by the kernel via cgroups. If a container exceeds its memory limit, the kernel's OOM killer terminates it rather than letting it consume the host's memory and affect other containers. This is important on shared hosts to prevent a single noisy or leaking container from starving everything else running alongside it. Compose supports the same controls under a service's deploy.resources (in Swarm mode) or the simpler mem_limit/cpus keys.

19. How do Docker registries and image push/pull work?

A registry is a storage and distribution service for Docker images, identified by repository names like docker.io/library/nginx or a private registry's own hostname; Docker Hub is the default public registry, but organizations commonly run private ones (via a self-hosted registry, ECR, GCR, ACR, etc.) for proprietary images. docker pull downloads an image's layers from a registry to the local machine, reusing any layers already cached locally, while docker push uploads a locally built and tagged image up to a registry so others (or other environments) can pull it. Before pushing, an image typically needs to be tagged with the target registry's address (docker tag myapp myregistry.com/myapp:1.0) so Docker knows where to send it. Authentication to private registries is handled via docker login, and CI/CD pipelines commonly automate build-tag-push as part of deployment.

Related topics
Kubernetes