Docker Interview Questions & Answers Part 02
Docker interview questions about architecture, troubleshooting, image security, operations, and deployment rollbacks.
Short answer: A virtual machine includes a complete guest operating system. A container shares the host kernel and isolates the application process.
| Feature | Container | Virtual machine |
|---|---|---|
| Operating system | Shares the host kernel | Includes a complete guest OS |
| Size | Usually measured in MBs | Usually measured in GBs |
| Startup | Usually seconds or less | Usually slower |
| Isolation | Process-level isolation | Hardware and OS-level isolation |
| Best fit | Application services and microservices | Different kernels or full OS environments |
Containers usually start faster and allow more workloads on one host. VMs provide a stronger boundary and are useful when workloads need separate operating systems or stronger isolation. The right choice depends on the security and operating-system requirements.
Short answer: Docker uses a client-server model. The Docker CLI sends requests to the Docker daemon, and the daemon performs the work.
- Docker CLI: The
dockercommand used to build, run, inspect, and remove resources. - Docker daemon: The service that manages images, containers, networks, and volumes.
- Image registry: A place such as Docker Hub, Amazon ECR, or Harbor where images are stored and downloaded.
For example, docker run nginx asks the daemon to pull the image if necessary and then create and start a container from it. The CLI and daemon can run on the same host or communicate with a remote Docker context.
Short answer: docker commit captures the current state of a container, while rebuilding from a Dockerfile creates a repeatable image from documented instructions.
You can use docker commit for a quick investigation or temporary recovery:
docker exec -it <container_name> sh
# Make a temporary change inside the container.
docker commit <container_name> myapp:debug
docker run --rm myapp:debug
For a real fix, update the Dockerfile and rebuild:
RUN apk add --no-cache curl
docker build -t myapp:2.0 .
The Dockerfile approach is preferred because the change is reviewable, reproducible, and easy to rebuild in CI. A committed container can also contain temporary files or secrets by accident.
Short answer: Check the container status, logs, exit code, events, configuration, and resource limits in that order.
# See status and restart count.
docker ps -a
# Read recent logs and include timestamps.
docker logs --timestamps --tail 200 <container_name>
# Check the exit code and Docker's error message.
docker inspect <container_name> \
--format '{{.State.Status}} exit={{.State.ExitCode}} error={{.State.Error}} oom={{.State.OOMKilled}}'
# Watch Docker events and resource usage.
docker events --filter container=<container_name>
docker stats <container_name>
Common causes include an application crash, a missing environment variable, a failed health check, an incorrect command, or an out-of-memory kill. Exit code 137 often indicates a process was killed for exceeding its memory limit, but confirm it with OOMKilled and host logs rather than relying on the number alone.
Short answer: Start with a suitable base image, copy only what the application needs, use multi-stage builds, and keep unnecessary files out of the build context.
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
Also add a .dockerignore file:
node_modules
.git
*.log
dist
Inspect the result with docker images and docker history. Avoid blindly choosing the smallest image: compatibility, patch availability, debugging needs, and security matter too.
Short answer: Build the image, scan it in CI, set a severity policy, and stop the pipeline when findings exceed that policy.
# Docker Scout
docker scout cves myapp:1.0
# Trivy
trivy image --severity HIGH,CRITICAL myapp:1.0
# Fail a CI job when a critical vulnerability is found.
trivy image --exit-code 1 --severity CRITICAL myapp:1.0
Scanning is not a one-time activity. Rescan deployed images because new vulnerabilities can be published after the image was built. Review whether a vulnerable package is reachable, update the base image or dependency, rebuild, and scan again.
Short answer: Confirm the finding, assess exposure, reduce immediate risk, rebuild with a fix, and redeploy through the normal release process.
# Confirm the finding and affected package.
trivy image --severity CRITICAL myapp:1.0
# Inspect the package when the image contains the required tools.
docker run --rm myapp:1.0 dpkg -l
# Rebuild after updating the base image or dependency.
docker build -t myapp:1.1 .
trivy image --exit-code 1 --severity CRITICAL myapp:1.1
For a critical internet-facing issue, temporarily restrict traffic, roll back to a known-good version, or apply a compensating control while the fix is prepared. Do not patch only the running container; that change disappears when the container is replaced. Fix the Dockerfile or dependency lock file and deploy a new image.
Short answer: A CVE is a public identifier for a known security vulnerability in software or a dependency.
For example, CVE-2024-1234 identifies one specific vulnerability. A scanner normally reports the affected package, installed version, fixed version, severity, and sometimes whether the vulnerable code is reachable.
Severity is often described using CVSS scores:
| CVSS score | Severity |
|---|---|
| 9.0-10.0 | Critical |
| 7.0-8.9 | High |
| 4.0-6.9 | Medium |
| 0.1-3.9 | Low |
A CVE in an image does not automatically prove that the application is exploitable. The package version, configuration, exposure, and actual code path should be assessed before deciding on the response.
Short answer: Explain how you confirmed the issue, assessed the risk, applied a temporary control, fixed the source, and prevented it from recurring.
A clear answer might sound like this:
Our image scan reported a critical vulnerability in the base image. We confirmed the affected package and checked whether the service was exposed. We restricted the affected endpoint while the fix was prepared, updated the base image, rebuilt and rescanned the image, then deployed it through the normal pipeline. We also added an automated scan and base-image update process so the issue would be detected earlier next time.
The important part is the process, not memorizing a CVE number. Keep the response factual and mention rollback, communication, evidence, and prevention where they apply.
Short answer: Use image scanners for detection and automated dependency tools for remediation.
| Tool | Main use |
|---|---|
| Trivy | Image, filesystem, and IaC scanning |
| Grype | Image and SBOM-based scanning |
| Docker Scout | Docker image analysis from the CLI |
| Snyk | Dependency and container scanning with fix guidance |
| Amazon ECR scanning | Registry-based image scanning |
| Dependabot or Renovate | Automated dependency and base-image update pull requests |
A practical CI flow is: build the image, generate or inspect its SBOM, scan for vulnerabilities, fail on the agreed severity threshold, and publish only approved images.
Short answer: Choose an official, supported, patched image that is compatible with the application and no larger than necessary.
For a Node.js service, I might compare node:22, node:22-slim, node:22-alpine, or a distroless runtime. A full image is convenient for building, while a slim or distroless image may be better for the final runtime.
I would consider:
- Application compatibility, especially native libraries and libc differences.
- Patch cadence and support for the chosen image.
- Image size and vulnerability count.
- Whether the runtime needs a shell or package manager for troubleshooting.
- Pinning a version or digest instead of using
latest.
The best answer is not always the smallest image. It is the image that meets the runtime, security, and operational requirements with a clear update process.
Short answer: Identify the container, inspect its image and mounts, check the files from inside the container, and review the startup logs.
docker ps
docker inspect <container_name> --format '{{.Config.Image}}'
docker exec -it <container_name> sh
ls -la /app
cat /app/config.json
docker inspect <container_name> --format '{{json .Mounts}}'
docker cp <container_name>:/app/config.json ./config.json
docker logs --tail 50 <container_name>
If the container has no shell, inspect the mounted host path or use docker cp. Do not edit files manually inside a production container as a permanent fix; change the source or image and redeploy it.
Short answer: Check disk usage first, remove only resources that are no longer needed, and be especially careful with volumes.
docker system df
docker container prune
docker image prune
docker builder prune
# Review carefully: removes all unused images.
docker image prune -a
# Review very carefully: unused volumes may contain important data.
docker volume prune
Avoid using docker system prune -a --volumes as an automatic cleanup command on a host that may contain important data. In CI, use an isolated runner or a documented cleanup policy with the least destructive commands needed.
Short answer: docker stop requests a graceful shutdown. docker kill stops the main process immediately by default.
# Give the application time to close connections and save state.
docker stop --time 30 mycontainer
# Use only when the container is unresponsive or must stop immediately.
docker kill mycontainer
# Send a specific signal when the application supports it.
docker kill --signal SIGHUP mycontainer
Use docker stop as the normal operation. A graceful application should handle the termination signal, finish or reject new work, and exit before Docker’s timeout expires.
Short answer: Validate required configuration at startup and fail with a clear message when a required value is missing.
docker exec mycontainer printenv APP_ENV
docker inspect mycontainer --format '{{json .Config.Env}}'
A simple entrypoint check can look like this:
#!/bin/sh
set -eu
: "${DB_HOST:?DB_HOST is required}"
: "${APP_SECRET:?APP_SECRET is required}"
exec "$@"
Keep secrets out of command output and logs. Use runtime secret injection for sensitive values, and validate that non-secret settings such as ports and hostnames have usable values before starting the application.
Short answer: Keep immutable versioned images, identify the last known-good version, switch traffic or restart the service with that image, and investigate the failed release afterward.
# Standalone Docker example.
docker stop myapp
docker rm myapp
docker run -d --name myapp myapp:1.0
# Compose: update the image tag to the known-good version.
docker compose up -d
# Swarm rollback.
docker service rollback myapp-service
For Kubernetes, use kubectl rollout undo deployment/myapp. Never use only the latest tag for production rollback decisions; record the exact image tag or digest deployed to each environment.
Short answer: Docker provides tools to build and run containers. Kubernetes orchestrates container workloads across a cluster.
| Area | Docker | Kubernetes |
|---|---|---|
| Main focus | Build images and run containers | Schedule and manage workloads across nodes |
| Scope | Commonly one host or a small Compose application | A cluster of worker nodes |
| Scaling | Usually manual | Declarative and automated options |
| Recovery | Docker restart policies | Controllers reschedule and replace failed Pods |
| Deployment | docker run or Compose | Deployments, Services, and other Kubernetes resources |
They are often used together: Docker or another image builder creates an OCI-compatible image, a registry stores it, and Kubernetes runs that image. Kubernetes does not need the Docker daemon as its container runtime.
Short answer: Verify the image reference, image digest, container mounts, build context, and deployment configuration before changing the running container.
docker inspect <container_name> --format '{{.Config.Image}}'
docker image inspect <image:tag> --format '{{json .RepoDigests}}'
docker inspect <container_name> --format '{{json .Mounts}}'
docker diff <container_name>
Typical causes include an old image tag, a stale local build cache, an incorrect build context, a bind mount hiding files copied into the image, or a deployment that was not recreated after the image changed. Use immutable tags or digests and verify the image ID in the deployment log.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form