Docker interviews test your understanding of containerisation fundamentals, image building, networking, storage, orchestration basics, and production patterns. This guide covers the 50 most common questions — with concise answers and real examples.
Quick reference
| Topic | Most asked questions |
|---|---|
| Core concepts | Image vs container, Docker daemon, layers |
| Dockerfile | Instructions, multi-stage builds, best practices |
| Networking | Bridge/host/overlay networks, port mapping |
| Volumes | Bind mounts vs volumes, tmpfs, data persistence |
| Docker Compose | Services, depends_on, override files |
| Registry | Push/pull, private registries, tagging |
| Security | Non-root user, secrets, image scanning |
| Performance | Build cache, layer optimisation, image size |
| Production | Health checks, logging, resource limits |
| Orchestration | Docker Swarm vs Kubernetes basics |
Core Concepts
1. What is Docker and why is it used?
Docker is an open-source platform that packages applications into containers — lightweight, portable units that include the application code, runtime, libraries, and system dependencies.
Key benefits:
- Consistency: same environment in dev, staging, and production
- Isolation: containers don't interfere with each other or the host
- Portability: runs on any OS that has the Docker Engine
- Efficiency: containers share the host OS kernel (unlike VMs)
2. What is the difference between a Docker image and a container?
| Aspect | Image | Container |
|---|---|---|
| Definition | Read-only template | Running instance of an image |
| State | Immutable, layered filesystem | Has a writable layer on top |
| Lifecycle | Built once, used many times | Created, started, stopped, deleted |
| Storage | Registry / local cache | Docker host |
| Analogy | Class definition | Object instance |
docker images # list images
docker ps # list running containers
docker ps -a # list all containers (including stopped)
3. Explain Docker's architecture (daemon, client, registry).
┌──────────────┐ ┌────────────────────────────────┐
│ Docker Client│─REST API─▶ Docker Daemon │
│ (docker CLI)│ │ - manages images/containers │
└──────────────┘ │ - handles networking/storage │
└────────────┬───────────────────┘
│ pull/push
┌───────▼───────┐
│ Docker Registry│
│ (Docker Hub, │
│ ECR, GCR …) │
└───────────────┘
- Docker daemon (
dockerd): background service that manages containers - Docker client (
docker): CLI that sends commands to the daemon via a REST API - Docker registry: stores and distributes images (Docker Hub is the default public registry)
4. What are Docker image layers and why do they matter?
Each instruction in a Dockerfile creates a read-only layer. Layers are cached and shared across images.
FROM ubuntu:22.04 # layer 1
RUN apt-get update # layer 2
RUN apt-get install -y python3 # layer 3
COPY app.py /app/ # layer 4
CMD ["python3", "/app/app.py"] # metadata
Benefits:
- Build cache: unchanged layers are reused, making rebuilds fast
- Storage efficiency: layers shared between images use disk only once
- Immutability: each layer is content-addressable (SHA256)
5. What is a Docker registry? What is Docker Hub?
A registry stores Docker images. Docker Hub is the default public registry.
docker pull nginx:1.25 # pull from Docker Hub
docker pull my.registry.io/app:v1 # pull from private registry
docker push my.registry.io/app:v1 # push to private registry
docker login my.registry.io # authenticate
Popular registries: Docker Hub, AWS ECR, Google Artifact Registry, GitHub Container Registry, self-hosted (Harbor, Nexus).
Dockerfile
6. What is a Dockerfile?
A Dockerfile is a text file with instructions that Docker reads to build an image. Each instruction creates a layer.
FROM node:20-alpine # base image
WORKDIR /app # set working directory
COPY package*.json ./ # copy dependency files first (cache optimisation)
RUN npm ci --only=production # install dependencies
COPY . . # copy source code
EXPOSE 3000 # document the port (informational only)
USER node # run as non-root
CMD ["node", "server.js"] # default command
7. What is the difference between CMD and ENTRYPOINT?
| Aspect | CMD | ENTRYPOINT |
|---|---|---|
| Purpose | Default arguments/command | Main executable |
| Override | docker run img <cmd> replaces it |
docker run img <args> appends to it |
| Shell form | CMD echo hi |
ENTRYPOINT echo hi |
| Exec form | CMD ["node", "app.js"] |
ENTRYPOINT ["node", "app.js"] |
Use ENTRYPOINT for the fixed executable + CMD for default arguments:
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
# docker run img -t → nginx -t (override CMD)
Always prefer exec form (["executable", "arg"]) over shell form — exec form doesn't spawn a shell, so signals are properly received.
8. What is the difference between RUN, CMD, and ENTRYPOINT?
- RUN: executes during build time, creates a new layer (install packages, compile code)
- CMD: executes at container start, sets default command/args, can be overridden
- ENTRYPOINT: executes at container start, defines the main process, not easily overridden
9. What is a multi-stage build and why use it?
Multi-stage builds use multiple FROM instructions to separate the build environment from the runtime image, producing smaller production images.
# Stage 1: build
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
USER node
CMD ["node", "dist/server.js"]
Benefits: build tools (compilers, dev dependencies) stay in the builder stage, final image only contains runtime artifacts.
10. What are Dockerfile best practices?
# 1. Use specific base image tags (not :latest)
FROM python:3.12-slim
# 2. Order: least-changed → most-changed layers (cache)
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . . # source changes often — put last
# 3. Combine RUN commands to reduce layers
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
# 4. Use .dockerignore
# 5. Run as non-root
RUN adduser --disabled-password appuser
USER appuser
# 6. Use COPY over ADD (COPY is explicit)
# 7. Use multi-stage builds
# 8. Set WORKDIR explicitly
WORKDIR /app
11. What is .dockerignore and why is it important?
.dockerignore tells Docker which files to exclude from the build context (sent to the daemon):
.git
node_modules
*.log
.env
dist
__pycache__
Benefits: smaller build context = faster builds, prevents accidentally leaking secrets (.env, credentials).
12. What is the difference between COPY and ADD?
| Feature | COPY | ADD |
|---|---|---|
| Local files | ✓ | ✓ |
| URL download | ✗ | ✓ |
| Auto-extract tar | ✗ | ✓ |
| Recommendation | Preferred (explicit) | Only when tar extraction needed |
Use COPY by default. ADD's extra features (URL fetch, auto-extract) can cause surprises.
13. What does EXPOSE do?
EXPOSE is documentation only — it tells users which port the container listens on. It does not actually publish the port to the host. You publish ports with -p:
docker run -p 8080:3000 myapp # host:container
Networking
14. What are the main Docker network types?
| Driver | Description | Use case |
|---|---|---|
bridge |
Default, isolated virtual network | Single-host container communication |
host |
Container uses host network stack | Max performance, no isolation |
none |
No networking | Fully isolated containers |
overlay |
Multi-host networking | Docker Swarm / distributed services |
macvlan |
Container gets MAC address on LAN | Legacy applications needing LAN access |
docker network ls
docker network create mynet
docker run --network mynet nginx
15. How do containers on the same bridge network communicate?
Containers on the same user-defined bridge network can reach each other by container name (Docker's built-in DNS resolves names):
docker network create mynet
docker run -d --name db --network mynet postgres
docker run -d --name app --network mynet myapp
# app can connect to db:5432
Containers on the default
bridgenetwork cannot use names — use custom networks.
16. What is the difference between -p and --expose?
-p 8080:3000: publishes port 3000 of the container to port 8080 on the host (accessible from outside)--expose 3000(orEXPOSEin Dockerfile): only makes the port accessible to other containers on the same Docker network, not to the host
17. What is a Docker overlay network?
Overlay networks span multiple Docker hosts, enabling containers on different machines to communicate. Used by Docker Swarm and Kubernetes (with the right network plugin).
docker swarm init
docker network create --driver overlay myoverlay
Volumes and Storage
18. How does Docker handle persistent storage?
By default, container data is lost when the container is removed. For persistence:
| Storage type | Description |
|---|---|
| Named volumes | Managed by Docker, stored in Docker area (/var/lib/docker/volumes/) |
| Bind mounts | Map a host path into the container |
| tmpfs mounts | In-memory only, not persisted to disk |
19. What is the difference between a bind mount and a named volume?
# Named volume (Docker managed)
docker run -v mydata:/app/data postgres
# Bind mount (host path)
docker run -v /host/path:/app/data postgres
# Read-only bind mount
docker run -v /host/config:/app/config:ro nginx
| Aspect | Named volume | Bind mount |
|---|---|---|
| Managed by | Docker | Host OS |
| Portability | High | Tied to host path |
| Performance | Optimal | Same or slightly lower on macOS/Windows |
| Use case | Database data, persistent state | Development (live reload), config injection |
Prefer named volumes in production. Bind mounts are great for development (source code live reload).
20. How do you share data between containers?
# Method 1: Named volume shared between containers
docker run -v shared:/data --name writer alpine sh -c "echo hello > /data/file.txt"
docker run -v shared:/data --name reader alpine cat /data/file.txt
# Method 2: --volumes-from (copy volume mounts)
docker run --volumes-from writer --name reader2 alpine cat /data/file.txt
21. What is a tmpfs mount?
An in-memory mount — data exists only while the container runs, never written to disk. Useful for sensitive data or performance-critical temporary data:
docker run --tmpfs /tmp:rw,size=100m myapp
Docker Compose
22. What is Docker Compose?
Docker Compose is a tool for defining and running multi-container applications using a YAML file (docker-compose.yml or compose.yml).
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
interval: 5s
timeout: 5s
retries: 5
volumes:
pgdata:
23. What is depends_on and what does it NOT guarantee?
depends_on controls start order — it ensures container B starts after container A. But it does not wait for container A's application to be ready (only for the container to start).
To wait for readiness, use condition: service_healthy with a healthcheck (as shown above), or use tools like wait-for-it.sh.
24. What are the key Docker Compose commands?
docker compose up -d # start all services (detached)
docker compose down # stop and remove containers
docker compose down -v # also remove volumes
docker compose logs -f app # follow logs for a service
docker compose ps # list service status
docker compose exec app bash # exec into running service
docker compose build # rebuild images
docker compose pull # pull latest images
docker compose restart app # restart a service
25. What are override files in Docker Compose?
Compose merges multiple files. The default override is docker-compose.override.yml:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Common pattern:
docker-compose.yml— base configdocker-compose.override.yml— dev overrides (auto-loaded)docker-compose.prod.yml— production overrides (explicit)
Images and Registry
26. How do you tag and push an image?
# Build and tag
docker build -t myapp:v1.2.3 .
docker tag myapp:v1.2.3 registry.example.com/myapp:v1.2.3
docker tag myapp:v1.2.3 registry.example.com/myapp:latest
# Push
docker login registry.example.com
docker push registry.example.com/myapp:v1.2.3
docker push registry.example.com/myapp:latest
27. What is the difference between docker pull and docker build?
docker pull: downloads an existing image from a registrydocker build: creates a new image from a Dockerfile
28. How do you reduce Docker image size?
# 1. Use slim/alpine base images
FROM python:3.12-slim # vs python:3.12 (much smaller)
FROM node:20-alpine # vs node:20
# 2. Multi-stage builds (leave build tools behind)
# 3. Clean package manager caches in the same RUN layer
RUN apt-get update && apt-get install -y git && \
rm -rf /var/lib/apt/lists/*
# 4. Use .dockerignore to exclude unnecessary files
# 5. Install only production dependencies
RUN npm ci --only=production
# 6. Combine RUN commands to merge layers
Useful tools: dive (explore image layers), docker image inspect, docker history.
29. What is docker image prune and why is it useful?
Removes dangling images (untagged images left after builds):
docker image prune # remove dangling images
docker image prune -a # remove all unused images
docker system prune # remove stopped containers, unused networks, dangling images
docker system prune -a # also remove all unused images
Container Lifecycle and Management
30. What is the difference between docker stop and docker kill?
| Command | Signal | Behaviour |
|---|---|---|
docker stop |
SIGTERM, then SIGKILL after 10s | Graceful shutdown |
docker kill |
SIGKILL (default) | Immediate termination |
Always prefer docker stop. Use docker kill only if a container is stuck.
31. What is the difference between docker run and docker exec?
docker run: creates and starts a new container from an imagedocker exec: runs a command inside an already running container
docker run -it ubuntu bash # new container, interactive
docker exec -it mycontainer bash # exec into running container
32. What are container restart policies?
docker run --restart=always nginx
docker run --restart=on-failure:3 myapp # retry up to 3 times
| Policy | Behaviour |
|---|---|
no |
Never restart (default) |
always |
Always restart, even after daemon restart |
on-failure |
Restart if exit code is non-zero |
unless-stopped |
Restart always, except if manually stopped |
Use always or unless-stopped for production services.
33. How do you set resource limits for a container?
docker run \
--memory="512m" \ # memory limit
--memory-swap="1g" \ # total memory + swap
--cpus="1.5" \ # CPU cores (can be fractional)
--cpu-shares=512 \ # relative CPU weight (default 1024)
myapp
Or in Docker Compose:
services:
app:
deploy:
resources:
limits:
cpus: "1.5"
memory: 512M
Health Checks
34. What is a Docker health check?
A command Docker runs periodically to determine if a container is healthy:
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
States: starting → healthy | unhealthy
docker ps # shows health status
docker inspect mycontainer | jq '.[0].State.Health'
Compose and Swarm use health status to route traffic and trigger restarts.
Security
35. Why should containers run as non-root?
Running as root inside a container is a security risk — if the container is compromised, root inside may map to root outside (especially with bind mounts). Always create and use a non-root user:
# Node.js — use built-in 'node' user
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN chown -R node:node /app
USER node
CMD ["node", "server.js"]
# Generic
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
36. How do you manage secrets in Docker?
Bad:
ENV DB_PASSWORD=supersecret # visible in image history!
Good:
# Docker Secrets (Swarm)
echo "mysecret" | docker secret create db_password -
# Compose with secrets file (v3.1+)
secrets:
db_password:
file: ./secrets/db_password.txt
services:
app:
secrets:
- db_password
# available at /run/secrets/db_password
In production, use external secret managers (AWS Secrets Manager, HashiCorp Vault, Kubernetes Secrets).
37. What is Docker Content Trust?
Docker Content Trust (DCT) uses digital signatures to verify image authenticity:
export DOCKER_CONTENT_TRUST=1
docker pull myregistry.io/myimage:v1.0 # verifies signature
38. How do you scan Docker images for vulnerabilities?
# Docker Scout (built-in)
docker scout cves myimage:latest
docker scout recommendations myimage:latest
# Trivy (popular open source)
trivy image myimage:latest
# Snyk
snyk container test myimage:latest
Scan images in CI/CD before pushing to production. Set policies to fail builds on CRITICAL vulnerabilities.
39. What is the principle of least privilege in Docker?
- Run as non-root (
USER) - Drop Linux capabilities:
--cap-drop=ALL --cap-add=NET_BIND_SERVICE - Use read-only filesystem:
--read-only - Limit syscalls with seccomp profiles
- No
--privilegedunless absolutely necessary
Logging and Monitoring
40. How does Docker logging work?
Docker captures stdout and stderr from container processes. The logging driver determines where logs go:
docker logs mycontainer # view logs
docker logs -f mycontainer # follow (tail -f)
docker logs --tail 100 mycontainer
# Configure logging driver
docker run --log-driver=json-file --log-opt max-size=10m --log-opt max-file=3 nginx
# Other drivers: syslog, journald, fluentd, awslogs, splunk
In docker-compose.yml:
services:
app:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
41. How do you monitor Docker containers?
docker stats # live CPU/memory/network/disk stats
docker stats --no-stream # snapshot
# Inspect a specific container
docker inspect mycontainer
docker top mycontainer # running processes inside
Production monitoring: Prometheus + cAdvisor (container metrics), Grafana (dashboards), ELK/Loki (logs).
Docker Compose and Multi-Container Patterns
42. How do you handle environment variables in Docker Compose?
services:
app:
image: myapp
environment:
NODE_ENV: production
PORT: 3000
env_file:
- .env # load from file (not committed to git)
# .env file (auto-loaded by Compose)
DATABASE_URL=postgres://user:pass@db:5432/mydb
SECRET_KEY=changeme
43. What is the difference between docker compose up, down, and stop?
| Command | Effect |
|---|---|
docker compose up -d |
Create + start containers |
docker compose stop |
Stop containers (keep them) |
docker compose start |
Start stopped containers |
docker compose down |
Stop + remove containers + networks |
docker compose down -v |
Also remove volumes |
Advanced Topics
44. What is the difference between Docker Swarm and Kubernetes?
| Aspect | Docker Swarm | Kubernetes |
|---|---|---|
| Complexity | Simple | Complex |
| Setup | docker swarm init |
kubeadm / managed K8s |
| Scaling | Easy | Powerful but complex |
| Auto-healing | Basic | Advanced |
| Networking | Overlay | Multiple CNI plugins |
| Ecosystem | Smaller | Huge (de-facto standard) |
| Use case | Simpler workloads, small teams | Large scale, enterprise |
45. What is a Docker registry mirror / pull-through cache?
A registry mirror caches images locally, reducing external pull latency and bandwidth:
// /etc/docker/daemon.json
{
"registry-mirrors": ["https://mirror.example.com"]
}
Companies run pull-through caches (Nexus, Harbor, ECR pull-through) to speed up builds and reduce Docker Hub rate limit issues.
46. What happens when you run docker build?
- Docker client sends the build context (current directory) to the Docker daemon
- Daemon reads the Dockerfile
- For each instruction, daemon checks the layer cache — if cached, reuse; otherwise execute
- Each
RUN,COPY,ADDcreates a new intermediate container, commits it as a layer - Final image is tagged and stored locally
47. What is BuildKit and why should you use it?
BuildKit is the modern Docker build engine (default since Docker 23.0):
# Enable on older Docker
DOCKER_BUILDKIT=1 docker build .
# Parallel build stages
# Better cache (cache mounts, bind mounts in RUN)
# Secret mounts (never written to image)
# Cache mount — pip cache persists across builds
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
# Secret mount — available during build, not in image
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci
48. How does Docker image layer caching work in CI/CD?
# GitHub Actions example
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myapp:latest
cache-from: type=gha # GitHub Actions cache
cache-to: type=gha,mode=max
Also: registry cache (type=registry), local cache (type=local).
49. How do you debug a failing container?
# 1. Check logs
docker logs mycontainer
docker logs --tail 50 mycontainer
# 2. Inspect exit code
docker inspect mycontainer | jq '.[0].State'
# 3. Exec into a running container
docker exec -it mycontainer sh
# 4. Start with override command (overrides CMD)
docker run -it --entrypoint sh myimage
# 5. Check resource usage
docker stats mycontainer
# 6. Events
docker events --filter container=mycontainer
# 7. Copy files out
docker cp mycontainer:/app/logs ./logs
50. What is Docker init (--init)?
When a container's main process doesn't properly handle signals or zombie processes, use --init to run a minimal init system (tini) as PID 1:
docker run --init myapp
Or in Compose:
services:
app:
init: true
This ensures:
- SIGTERM is properly forwarded to child processes
- Zombie processes are reaped
- Container stops cleanly
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
| Running as root | Security risk if container is compromised | Add USER nonroot in Dockerfile |
| Storing secrets in env vars | Visible in docker inspect, image history |
Use Docker secrets, secret mounts, or external vault |
Using :latest tag |
Unpredictable builds, no reproducibility | Pin specific version tags |
One RUN per package install |
Excessive layers, bloated image | Combine with &&, clean caches in same layer |
No .dockerignore |
Slow builds, risk of leaking .env/.git |
Add comprehensive .dockerignore |
| Ignoring health checks | Compose/Swarm starts traffic before app is ready | Add HEALTHCHECK + condition: service_healthy |
| Bind-mounting entire source in prod | Includes dev files, security risk | Use COPY + named volumes for data |
| Not limiting resources | Container can starve the host | Set --memory and --cpus limits |
Docker vs Alternatives
| Tool | Type | Best for |
|---|---|---|
| Docker | Container runtime + tooling | General container development |
| Podman | Daemonless container runtime | Docker alternative, rootless |
| containerd | Low-level runtime | Used by Kubernetes under the hood |
| Buildah | Image builder (OCI) | Building images without Docker daemon |
| Kaniko | Build images in Kubernetes | CI/CD inside K8s (no Docker socket needed) |
| nerdctl | containerd CLI | Docker-compatible CLI for containerd |
FAQ
Q: Should I use FROM scratch for minimal images?FROM scratch is the empty base image — used for statically compiled binaries (Go, Rust). For most apps, use distroless or slim images instead (they include CA certs and minimal OS utilities).
Q: What is the difference between Docker Desktop and Docker Engine?
Docker Desktop is the GUI application for Mac/Windows that includes Docker Engine, Docker Compose, and other tools in a VM. Docker Engine is the core daemon that runs natively on Linux.
Q: Can Docker containers talk to the host database?
Use the special hostname host.docker.internal (Docker Desktop) or the host's gateway IP. In Linux, pass --network=host or use 172.17.0.1 (default bridge gateway).
Q: Is Docker the same as a VM?
No. VMs virtualise hardware and run a full OS per VM. Containers share the host OS kernel and isolate processes — much lighter and faster to start, but less isolated.
Q: Why does my container exit immediately?
The main process (CMD/ENTRYPOINT) exited. Docker containers run as long as their main process lives. Common fix: ensure the app stays in the foreground (don't daemonize), or use tail -f /dev/null for debugging.
Q: What is the difference between docker compose and docker-compose?docker-compose is the older standalone Python tool (v1). docker compose (with a space) is the modern Go plugin integrated into the Docker CLI (v2, current). Use docker compose for new projects.