A sample of real Docker interview questions with full answers and explanations - practice for interviews or certification exams.
It doesn't matter whether an instruction is RUN, COPY, or ENV, EVERY single one produces its own distinct image layer, and Docker caches all of them the same way. As long as nothing upstream of a given instruction has changed, that layer's cache can be reused on the next build.
Without a memory limit, a leaking container can eat up all the memory on the host, and the kernel may end up killing other innocent processes and containers to free up RAM. Setting a per-container memory limit means only that container gets capped and eventually killed for exceeding it, protecting everything else running on the same machine.
Because 'latest' is just a movable label that can point to a different image at different times, nodes that already have an older image cached under that same name have no reason to know it's now stale. Tagging each build with something immutable, like the git commit SHA or the image digest, means every node is referencing one specific, unambiguous version, so there's no room for this kind of silent mismatch.
docker-compose lets you describe multiple related services, like your app, a database, and a cache, in one YAML file and bring them all up together with one command, which matches this scenario exactly. A Dockerfile only describes how to build a single image, it doesn't coordinate multiple running services at once.
Copying just package.json first means Docker's cache for the 'install dependencies' layer only gets invalidated when that FILE actually changes, not whenever any application code changes. Since app code changes far more often than dependencies do, this ordering means the (often slow) install step gets skipped and reused on most rebuilds instead of rerunning every time.
By default, Swarm's rolling update behavior can continue replacing replicas even after failures show up, unless you've explicitly configured a failure_action, like pausing the rollout or automatically rolling back to the previous working version once health checks start failing. Removing the health check would make this worse, not better, since it's the very thing that would have caught the bad deployment in the first place.
Real applications are rarely just one container, they're usually several services working together (an app, a database, a cache). docker-compose lets you describe all of those services, plus how they network and store data, in one YAML file, so the whole group can be started or stopped together with a single command instead of managing each container by hand.
The always and unless-stopped restart policies bring the container back up no matter why it exited, including a perfectly normal, successful completion, which is the wrong behavior for a one-shot job. Switching the policy to no, or on-failure if you only want retries after actual errors, lets the job run once and stay stopped.
Binding to 127.0.0.1 specifically means 'only reachable from THIS exact loopback interface', which inside a container is its OWN internal loopback, not something reachable from outside via the container's real IP address. A health check hitting the container's IP address gets refused because the app was never actually listening on that address, only on its own internal localhost.
--userns-remap works by mapping container UIDs, including what LOOKS like root inside the container, to a completely unprivileged UID range on the actual host. That means even if an attacker somehow breaks out of container isolation entirely, they land as an unprivileged host user, not real root, which is exactly the containment this setting buys you.
Real scenario-based DevOps questions, hands-on practice, and clear explanations for every answer.