Docker Interview Questions
Crack your Docker interview with 47 in-depth questions covering containers vs VMs, images, Dockerfiles, Docker Compose, networking, volumes, multi-stage builds, layer caching, namespaces, cgroups, and container security - explained in plain English with real command and config examples.
I. Beginner Level
1. What is Docker, and why was it created?
Docker is an open-source containerization platform that packages applications and all their dependencies (libraries, runtimes, configs) into lightweight execution units called containers. It was created to eliminate the "it works on my machine" problem by ensuring consistent execution across development, testing, and production environments.
The process of containerization allows developers to package an application and all its dependencies into a Docker image. This image can be shared and deployed on any machine that supports Docker. When the image is executed, it runs as a container which is a lightweight, isolated runtime instance that shares the host operating system’s kernel.
2. Containerization v/s Virtualization?
| Virtualization | Containerization |
|---|---|
| Uses Virtual Machines (VMs) to run applications. | Uses Containers to run applications. |
| Each VM has its own guest operating system. | Containers share the host operating system's kernel. |
| Requires a hypervisor (e.g., VMware, VirtualBox, Hyper-V). | Uses a container runtime (e.g., Docker, containerd). |
| Higher resource usage and slower startup. | Lower resource usage and faster startup. |
| Best for running multiple operating systems or legacy applications. | Best for microservices, cloud applications, and fast deployments. |
| Goal: Complete OS-level isolation. | Goal: Lightweight application-level isolation. |
3. Core difference between a Virtual Machine (VM) and a Docker Container?
| Feature | Virtual Machine (VM) | Docker Container |
|---|---|---|
| Architecture | Hardware Virtualization (via Hypervisor) | OS Kernel Sharing (Process Isolation) |
| Operating System | Each VM runs its own full Guest OS | Shares host machine's Linux Kernel |
| Resource Overhead | High (Requires dedicated RAM/CPU allocation) | Extremely low (Shares host CPU/Memory dynamically) |
| Boot Time | Minutes | Seconds or milliseconds |
| Storage Size | Gigabytes to tens of Gigabytes | Megabytes |
4. What is a Docker Image?
A Docker Image is a read-only, immutable blueprint containing everything needed to run an application. An image is constructed from a stack of distinct, read-only layers, where each layer represents an instruction (such as installing a package or copying code).
Think of an image as a snapshot, a read-only template that has your app's code, the runtime it needs, system libraries, and any configuration that is required. Images are built in layers (usually from a Dockerfile), and once built, they don't change. You spin up containers from them, potentially many at once, all sharing those same underlying read-only layers.
5. What is Docker Container?
A Docker Container is a running instance of a Docker Image.
When you start a container from an image, Docker adds a thin, temporary read-write layer on top of the stacked read-only image layers. Any changes made while the container is running such as writing to a log file or modifying a temporary file all of them happen exclusively in this top writable layer. When you stop the container that writable layer's changes go away with it unless you've set up persistence.
6. What is a Docker file?
It's just a plain text file with a sequence of build instructions like which base image to start from, what to copy in, what commands to run, what port to expose, and what command to execute when the container starts. Docker reads it top to bottom and turns each instruction into a layer of the final image. It's basically the recipe for your image. Each line represents a build command (such as FROM, RUN, COPY) that produces a distinct, cached layer in the final image.
7. What are the features of Docker?
The key features of using Docker are :
Packages an app and its dependencies into a portable, isolated unit.
Runs many containers efficiently on one host by sharing the kernel.
Portable across operating systems and cloud providers.
Isolates processes and filesystems for better security.
Builds images in layers, enabling caching, reuse, and version control.
8. What are the advantages and disadvantages of using Docker?
Advantages of using Docker are :
Portability: Docker allows you to deploy the application in many different environments without changes.
Isolation: Docker keeps each application separate which adds security by isolating processes and file systems
High Computation Density : Packs significantly more applications onto a single host server compared to traditional virtual machines.
Streamlined CI/CD : Build an artifact once in your build pipeline, test it, and deploy that exact same byte-for-byte image to production without thinking about errors.
Disadvantages of using Docker are :
Learning Curve: Learning Docker and its container concepts can feel new and difficult at first.
Additional Resources: Docker containers can use system resources than running programs directly on the host.
Security Concerns: Misconfiguring Docker can create security risks that need attention.
Complexity: Managing Docker orchestration tools can become difficult when you scale up to containers.
9. What is Docker Hub, and how does image distribution work?
Docker Hub is a cloud-based registry hosted by Docker for storing and sharing container images, basically a giant library of container images that anyone can push to or pull from. When you build an image, you can tag it and docker push it up to Hub (public or a private repo). Anyone with access can then docker pull it down on their own machine.
Under the hood, images are pulled/pushed layer by layer, so if you already have some of the layers locally, only the missing ones get downloaded.
When an image is pushed:
Docker breaks the image down into its structural layers and compresses them into tarball chunks.
Each layer is assigned an identifier based on its content hash.
The layers and an overall JSON manifest file are uploaded to the registry.
When another user pulls the image, Docker checks which layer hashes already exist on the local machine and downloads only missing layers, minimizing network usage.
10. What is Docker Desktop, and how does it run on non-Linux systems like Windows or macOS?
Docker Desktop is the packaged app that gives you Docker plus a GUI on Windows and Mac. As containers depend on Linux kernel features (namespaces and cgroups), they cannot run directly on the macOS (Darwin) or Windows (NT) kernels.
So Docker Desktop quietly runs a lightweight Linux VM under the hood :
On Windows : It uses WSL 2 (Windows Subsystem for Linux 2) or Hyper-V to run a real Linux kernel directly integrated into Windows.
On macOS: It uses Apple’s native Virtualization.framework to spin up a minimal Linux VM. The Docker CLI running in your Mac or Windows terminal transparently redirects commands to the daemon inside this background Linux VM.
11. What is the Docker Client-Server architecture, and how do its components interact?
Docker runs as a client-server architecture setup. The client is the docker CLI you type commands into. The server is the dockerd daemon running in the background, doing the actual heavy lifting like building images, running containers, managing networks and volumes. They talk over a REST API, usually through a local Unix socket, though it can also be exposed over a network if you configure it that way.
The process by which components interact are :
User Action: A developer types a command like docker run -p 80:80 nginx into their shell.
API Transport: The Docker CLI translates this request into an HTTP REST API call and sends it over a local Unix socket (/var/run/docker.sock) to the Docker Daemon (dockerd).
Image Retrieval: dockerd checks if the nginx image is available in local cache. If missing, it communicates with Docker Hub over HTTPS to pull the image layers.
Process Execution: dockerd hands the execution request to containerd, which calls runc. runc interacts directly with the Linux kernel to create isolated namespaces and resource limits, mounting the storage layers and launching the application process.
12. What is the lifecycle of a Docker container?
A Docker container moves through a handful of state and is always in one of these states, which directly affects how it interacts with host operating system :
Created: The container directory structure, network interfaces, and namespaces are allocated from an image (docker create), but no process is executing.
Running: The main process inside the container is actively executing (docker start or docker run).
Paused: Execution is temporarily suspended using the cgroup freezer, preserving state in RAM (docker pause).
Stopped: The primary process has been signaled to exit and execution has halted, but the writable container layer remains intact on disk (docker stop).
Deleted: The writable layer and container metadata are permanently purged from the host storage (docker rm).
13. How do you start, stop and kill a container?
Start an existing stopped container: docker start <container_name_or_id>
Gracefully stop a running container: docker stop <container_name_or_id>
Immediately terminate a running container: docker kill <container_name_or_id>
1docker start <container_name_or_id> # resume a stopped container
2docker stop <container_name_or_id> # graceful shutdown (SIGTERM, then SIGKILL after timeout)
3docker kill <container_name_or_id> # immediate shutdown (SIGKILL right away)14. What basic commands manage the lifecycle of a container?
1docker run <image> # create and start a container
2docker ps # list running containers
3docker ps -a # list all containers, including stopped
4docker start <name> # start a stopped container
5docker stop <name> # gracefully stop it
6docker restart <name> # stop then start again
7docker rm <name> # remove it15. How do you permanently remove a container and an image?
The ways are :
Remove a stopped container: docker rm <container_id> (Use -f to force remove a running one).
Remove an unused image: docker rmi <image_id>
Clean up all stopped containers, unused networks, and dangling images at once: docker system prune
1docker rm <container_id> # remove a (stopped) container
2docker rm -f <container_id> # force-remove even if it's running
3docker rmi <image_id> # remove an image
4docker system prune # clean up unused containers, images, networks in one go16. What is the difference between docker stop and docker kill?
The difference between docker stop and docker kill
docker stop is the polite way — it sends a SIGTERM, gives the app a grace period (default 10 seconds) to shut down cleanly, and only then sends SIGKILL if it hasn't exited.
docker kill skips the courtesy entirely and sends SIGKILL immediately, which is faster but risks leaving things in a messy state (unflushed writes, half-finished transactions). The kernel halts execution instantly without giving the app a chance to run cleanup routines.
17. How do you inspect a container's logs and current running processes?
View stdout/stderr logs: docker logs -f --tail 100 <container_name> (The -f flag streams logs live, while --tail 100 shows the last 100 lines).
View active internal processes: docker top <container_name> (Displays the container processes running on the host OS alongside their host PIDs).
18. How do dangling images differ from unused images?
Dangling Images: A dangling image is a leftover, untagged layer, you'll see it show up as <none> when you run docker images, usually it's left behind after rebuilding an image with the same tag (the old layer gets orphaned).
Untagged image layers listed as <none>:<none> are dangling images. They can occur when you build an image with an existing tag name; Docker applies the tag to the new image, leaving the old image layers untagged. We can clean them up with command docker image prune.
Unused Images:An unused image is a fully tagged image stored on disk that is simply not actively assigned to any currently existing container instance. It is a legitimate image that just isn't currently backing any running or stopped container.
II. Intermediate Level
1. What is a Docker Volume, and why is it used?
By default, data written inside a running container lives in its temporary read-write layer. If the container is deleted, that data is lost permanently. Additionally, reading/writing through the storage driver adds a performance penalty.
A Docker Volume is a storage directory created and managed directly by Docker on the host disk (typically in /var/lib/docker/volumes/). It exists independently of the container lifecycle. Mounting a volume to a container bypasses the temporary storage driver, delivering full native I/O performance while ensuring data persists even if the container is destroyed.
2. Why are container filesystems ephemeral (long lasting), and how does Docker handle data persistence?
Container filesystems are ephemeral because they use a thin copy-on-write layer tied directly to the lifecycle of that container instance. If a container crashes or is deleted, its writable layer is destroyed along with all uncommitted changes. By design, a container's writable layer is meant to be disposable and that's what makes containers easy to recreate, replace, and scale without worrying about leftover state. But that also means anything written there vanishes when the container is removed.
Docker handles data persistence by decoupling storage from the container lifecycle using two main mechanisms:
Volumes: Directories stored in /var/lib/docker/volumes/ managed by Docker. They are independent of container life cycles and can be shared between containers.
Bind Mounts: Direct mappings of any arbitrary, specified host directory or file (e.g., /home/user/app/logs) into the container.
3. How do you create and mount a Docker Volume?
1# 1. Create a managed Docker volume explicitly
2docker volume create db-data
3
4# 2. Mount the volume into a container path (e.g., PostgreSQL data directory)
5docker run -d \
6 --name postgres-db \
7 -v db-data:/var/lib/postgresql/data \
8 postgres:154. What is Docker Compose?
Docker Compose is a tool used to define, configure, and organises multi-container application environments. Instead of running complex CLI commands sequentially for every microservice, you describe your entire architecture like web servers, databases, cache layers, networks, and storage mounts in a single declarative file (docker-compose.yml). You can then launch or stop all interconnected services using one command (docker compose up).
5. What does a typical docker-compose.yml file look like?
A typical docker-compose.yml file is a hierarchical YAML blueprint that configures and orchestrates multi-container applications by defining services (containers), networks, and volumes.
Here is what a complete, standard docker-compose.yml file looks like for a typical web application stack (a Python web app running with a Redis database):
1version: "3.8"
2
3services:
4 web:
5 build: .
6 ports:
7 - "8000:8000"
8 volumes:
9 - .:/code
10 environment:
11 - DEBUG=true
12 depends_on:
13 - redis
14 networks:
15 - app-network
16
17 redis:
18 image: "redis:alpine"
19 volumes:
20 - redis-data:/data
21 networks:
22 - app-network
23
24volumes:
25 redis-data:
26
27networks:
28 app-network:
29 driver: bridgeA basic Compose file is divided into four main root-level sections:
version: "3.8": Specifies the specific file format version being used, ensuring compatibility with your local Docker Engine installation
Services :
build / image: Defines where the container comes from. build: . tells Docker to build a custom image using a local Dockerfile, while image: "redis:alpine" pulls a pre-made image directly from Docker Hub.
ports: Maps standard host machine ports to container ports (formatted as "host:container") so you can access the application from your browser.
volumes: Mounts folders. ./:/code maps your current local directory to the container for live code reloading during development.
environment: Passes critical environment variables inside the container at runtime.
depends_on: Dictates the startup order, forcing dependency containers (like databases) to launch before the application container starts
volumes:: Declares persistent storage blocks (redis-data). This prevents data inside your databases or file uploads from erasing whenever a container restarts or is destroyed
networks:: Explicitly defines custom virtual networks (app-network). Containers sharing the same network can safely communicate with each other using their service names (e.g., the web app connecting to redis://redis:6379
6. What is the difference between docker compose up, stop, down, and start?
docker compose up: Builds missing images, creates defined networks/volumes, and launches all containers.
docker compose stop: Halts execution of running containers without deleting container instances, networks, or volume bindings.
docker compose start: Restarts existing containers that were halted by stop.
docker compose down: Completely stops and removes containers, networks, and default volumes created by up.
7. What is the difference between docker exec and docker attach?
docker exec: Creates a new process inside an already running container. Common for opening a separate interactive shell for debugging (docker exec -it <container_name> /bin/bash) without disturbing the main process.
docker attach: Connects your local terminal's standard input/output directly to the primary running process (PID 1) inside the container. If you exit or send Ctrl+C while attached, you will terminate the container’s primary process and stop the container.
8. What is a Dockerfile, and what are its essential instructions?
A Dockerfile is a plain text file containing a sequential script of instructions used to automatically build a Docker image. Think of it as a recipe: the Dockerfile lists the ingredients and steps, the Docker image is the cooked meal (a packaged executable template), and a Docker container is a single serving being eaten (a running instance of that image). In short, it's the build script for an image.
The instructions you'll use constantly:
FROM: Sets the initial base image (e.g., FROM node:18-alpine).
WORKDIR: Sets the working directory for subsequent instructions.
COPY/ADD: Copies files from the host machine into the container filesystem.
RUN: Executes commands during the build stage to install packages or compile code (creates a new image layer).
EXPOSE: Informs Docker which port the container listens on at runtime (documentation metadata).
ENV: Sets persistent environment variables inside the container.
CMD/ENTRYPOINT: Specifies the default command to execute when the container boots.
Less common but still useful: USER (run as non-root) and VOLUME (declare a mount point).
9. What is the difference between RUN, ENTRYPOINT, and CMD in a Dockerfile?
RUN: Executes commands at image build time. It's how you install packages or set things up, and each RUN creates a new image layer. Used to modify the filesystem image (e.g., RUN apt-get update && apt-get install -y curl).
ENTRYPOINT: Defines the core executable that should always run when the container starts. It is difficult to override via the command line.
CMD: Defines the default parameters or fallback command passed to ENTRYPOINT. It is easily overridden at runtime by passing arguments at the end of docker run.
A common pattern combines both : ENTRYPOINT fixes the program, CMD supplies default arguments to it.
For example:
1ENTRYPOINT ["python3"]
2CMD ["app.py"] # Can be overridden by running: docker run my-image test.py10. What is the standard process for publishing an image to Docker Hub?
Log in to Docker Hub: Open your terminal and run docker login. Enter your Docker Hub username and password when prompted.
Build your image: Create a Dockerfile and build your image locally using the command docker build -t <image-name>
Tag your image: Tag the local image with your Docker Hub username and repository name using docker tag <local-image-name> <dockerhub-username>/<repository-name>:<tag>. (The default tag is usually latest)
Push the image: Upload the image to Docker Hub by running docker push <dockerhub-username>/<repository-name>:<tag>
1# 1. Authenticate with Docker Hub
2docker login
3
4#2. Build your image
5docker build -t yourusername/my-app:1.0
6
7# 3. Tag local image with your Docker Hub username and repository name
8docker tag local-app:1.0 username/my-app:1.0
9
10# 4. Push the image to the remote registry
11docker push username/my-app:1.011. What are the built-in Docker network drivers?
The built in Docker network drivers are :
bridge: The default network driver. Creates a virtual software bridge (docker0) on the host. Containers on the same bridge network can communicate via private IP addresses. In simple language, they can talk to each other.
host: Completely removes network isolation between the container and the host machine. The container shares the host's IP address and port namespace directly. No isolation, no NAT.
none: Disables all networking interfaces except the internal loopback (127.0.0.1). Meaning no networking at all.
overlay: Enables multi-host networking across separate physical Docker hosts basically it connects containers across multiple Docker hosts, and is used in Swarm mode.
macvlan: Assigns a distinct MAC address to the container, making it appear as a physical network device on your local router network.
12. How do port publishing and port forwarding work in Docker ( -p flag)?
By default, containers on a bridge network get private internal IPs accessible only to other containers on that host. To make an app accessible externally, you publish ports using
1-p <host_port>:<container_port>.Behind the scenes, Docker configures ip tables (Network Address Translation - NAT) rules on the host OS. When traffic hits <host_port> on the host's network interface, ip tables intercepts and routes those packets into the container's private virtual network interface at <container_port>.
For example, docker run -p 8080:80 myimage maps port 8080 on the host to port 80 inside the container, so traffic hitting the host on 8080 gets forwarded in. Without -p, the container's ports stay reachable only from other containers on the same Docker network, not from outside. EXPOSE in a Dockerfile is just documentation, it doesn't actually open anything to the outside world. The -p flag is what actually does the job.
13. What is the role of a .dockerignore file?
Before building an image, the Docker CLI sends the directory contents (the "build context") to the Docker Daemon. A .dockerignore file prevents specified files and directories (like .git/, node_modules/, local .env files, logs) from being transferred to the daemon. This speeds up build times, avoids cache invalidation, and prevents sensitive credentials from leaking into the final image layers. It works exactly like .gitignore, but for Docker builds, it tells Docker which files and folders to skip when sending the build context to the daemon.
So the purpose of .dockerignore file is to build fast by not shipping huge folders like node_modules or .git unnecessarily, and it stops sensitive files (like .env with real credentials) from accidentally ending up baked into an image layer.
14. What is the difference between exec form and shell form in Dockerfile commands?
Exec Form (CMD ["node", "server.js"]): Parses the array as a JSON string. The executable runs directly as PID 1 inside the container. Signal forwarding works properly; when docker stop sends SIGTERM, your application handles it directly.
Shell Form (CMD node server.js): Wraps the command inside /bin/sh -c node server.js. The shell process becomes PID 1, and your application becomes a child process. The shell will typically ignore SIGTERM signals, breaking graceful shutdown routines.
15. What is a multi-stage Docker build, and why is it important?
A multi-stage build lets you use several FROM instructions in one Dockerfile, where each one starts a fresh "stage."
You typically use an earlier stage with all your build tools (compilers, dev dependencies) to actually build the app, then copy only the finished output into a clean, minimal final stage. It is important because it keeps your production image lean as none of that build tooling ships in the final image, which shrinks size and reduces attack surface.
Traditional Dockerfiles require heavy software tooling (compilers, build tools, SDKs) to compile source code, resulting in bloated production images. Multi-stage builds solve this by using multiple FROM instructions in a single Dockerfile. You build binaries in early, heavy stages, then copy only the final compiled artifact into a clean, minimal runtime image.
16. How do you create a multi stage build?
1# Stage 1: Build & Compilation stage
2FROM golang:1.20-alpine AS builder
3WORKDIR /build
4COPY go.mod go.sum ./
5RUN go mod download
6COPY . .
7RUN CGO_ENABLED=0 GOOS=linux go build -o main .
8
9# Stage 2: Final minimal production image
10FROM alpine:3.18
11WORKDIR /app
12# Copy ONLY compiled binary from the builder stage
13COPY --from=builder /build/main .
14EXPOSE 8080
15CMD ["./main"]OR
1FROM golang:1.22 AS builder
2WORKDIR /src
3COPY . .
4RUN go build -o app
5
6FROM alpine
7COPY --from=builder /src/app /app
8CMD ["/app"]17. How can you minimize the size of a production Docker image?
The steps you can follow to minimize the size of production Docker image are :
Use Minimal Base Images: Choose alpine or distroless base images instead of standard ubuntu or debian.
Implement Multi-Stage Builds: Exclude build tools, compilers, and source files from the final image
Combine RUN Commands: Execute related setup actions in a single RUN layer using && and clear temporary caches in the same line (e.g., apt-get install -y pkg && rm -rf /var/lib/apt/lists/*).
Exclude Unnecessary Files: Use a .dockerignore file to exclude local build artifacts and node modules.
18. How does Docker layer caching work, and how can you optimize Dockerfiles to leverage it?
Every instruction in a Dockerfile becomes a cached layer. On a rebuild, Docker walks through the file and reuses a cached layer as long as that instruction and its inputs haven't changed but the moment it hits one that has changed, every layer after it gets rebuilt from scratch, cache or not. That means if a layer’s input files change, Docker invalidates the cache for that layer and all subsequent layers.
Also, Docker builds images sequentially, each instruction in a Dockerfile creates a read-only layer cached on disk.
To optimize caching, arrange instructions from least frequently changed to most frequently changed:
1 FROM node:18-alpine
2WORKDIR /app
3
4# Step 1: Copy dependency descriptors FIRST (changes rarely)
5COPY package.json package-lock.json ./
6RUN npm install # Layer stays cached unless dependencies change!
7
8# Step 2: Copy application code LAST (changes often)
9COPY . .
10CMD ["npm", "start"]19. How do health checks work in Docker, and why are they vital?
The HEALTHCHECK instruction tells Docker to periodically run a command inside the container to verify the app is actually functioning, not just that the process is technically alive. If that check fails enough times in a row, Docker marks the container unhealthy, which orchestration tools can then act on (restarting it, pulling it out of a load balancer, etc.). Without this, a container can look "running" from the outside while the app inside is completely frozen or broken.
By default, Docker only checks if a container process is running. However, a process might be running (e.g., trapped in an infinite loop) while failing to serve application requests. The HEALTHCHECK periodically executes a command inside the container to test real application health.
1HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
2 CMD curl -f http://localhost:8080/health || exit 1If the command fails 3 consecutive times, Docker marks the container status as unhealthy, alerting orchestrators (like Docker Swarm or Kubernetes) to restart or replace the container.
20. How does Docker handle container restart policies?
Restart policies dictate how Docker reacts when a container exits or crashes, and they are :
--restart no: (Default) Never restart the container automatically.
--restart on-failure[:max_retries]: Restarts only if the container process exits with a non-zero exit code (failure).
--restart always: Always restarts the container regardless of exit reason. If manually stopped, it restarts upon Docker daemon reboot.
--restart unless-stopped: Always restarts the container except when manually stopped by a user command.
21. How do you set hard limits on CPU and Memory usage for containers?
To prevent a compromised or leaking container from crashing the host node, you enforce cgroup resource caps at runtime:
--memory="512m": Caps memory usage at 512MB. Exceeding this triggers OOM limits.
--cpus="1.5": Restricts execution to a maximum of 1.5 CPU cores worth of computing cycles.
(Code snippet)
1docker run -d \
2 --name resource-constrained-app \
3 --memory="512m" \
4 --cpus="1.5" \
5 nginx:alpineIII. Advanced Level
1. What are the main OS isolation mechanisms that make Linux containers possible?
Two kernel features do most of the heavy lifting which are :
Namespaces : these provide a container its own isolated view of things like process IDs, network interfaces, and mount points and also gives resource visibility isolation (determines what a process can see).
Control groups (cgroups) : These groups limit and track how much CPU, memory, and I/O a container is allowed to use. Basically it provides resource allocation limits (determines how much a process can use).
2. How do Namespaces isolate resources inside a container?
Namespaces partition system resources so a process inside a container believes it is running on its own dedicated machine. Each namespace type hides a different slice of the system from the container.
PID Namespace: Gives processes isolated Process IDs. Inside the container, your web server sees itself as PID 1 (the init process), even though the host kernel sees it as PID 10482.
NET Namespace: Isolates network controllers, routing tables, and IP addresses, giving each container its own virtual loopback and network interfaces.
MNT Namespace: Isolates file system mount points, ensuring a container only sees its assigned root filesystem.
IPC Namespace: Restricts Inter-Process Communication (shared memory segments, semaphores).
UTS Namespace: Allows the container to have its own hostname independent of the host system.
USER Namespace: Maps UID/GIDs inside the container to different UIDs/GIDs on the host (e.g., container root mapped to an unprivileged user on host).
3. How do Control Groups (cgroups) manage container resources?
While Namespaces hide resources, cgroups meter and restrict physical resource consumption. Control groups are the enforcement layer, they cap and account for how much CPU, memory, disk I/O, and network bandwidth a container (or group of processes) can actually use. This is what stops one noisy container from starving every other container on the same host.
It's the mechanism behind flags like --cpus and --memory when you run a container. They allow the Linux kernel to enforce hard or soft limits on hardware access which are:
Memory Limits: Set caps on total RAM usage to prevent a memory leak in one container from triggering the kernel's Out-Of-Memory (OOM) killer on the whole host.
CPU Shares & Quotas: Allocate specific CPU cores or percentage shares of processing cycles.
Disk I/O: Restrict read/write bandwidth speeds to specific storage devices.
4. Why is running containers as the root user a security risk, and how do you fix it?
By default, Docker containers run process tasks as root. Because containers share the host's Linux kernel, an attacker who exploits a vulnerability inside the container could break out of container boundaries and gain full root-level control over the physical host machine. The risk we are talking about is that if an attacker manages to break out of the container (through a kernel exploit or a container misconfiguration), root inside the container can translate to real privilege on the host.
The fix is straightforward: add a USER instruction in your Dockerfile to switch to a non-root user before the app runs, and where possible, run the container itself with a read-only root filesystem and dropped Linux capabilities for extra hardening.
Let us understand with the help of an example :
Fix: Create and switch to an unprivileged non-root user inside your Dockerfile:
1FROM node:18-alpine
2WORKDIR /app
3COPY . .
4
5# Create non-root user and switch to it
6RUN addgroup -S appgroup && adduser -S appuser -G appgroup
7USER appuser
8
9CMD ["node", "app.js"]5. How do you handle sensitive configuration data (secrets) in Docker?
The one thing you should never do is bake secrets into the image via ENV or ARG, they end up permanently visible in the image's layer history, extractable by anyone who pulls it.
Bad Practice: Hardcoding secrets into Dockerfiles, images, or committing them to git. Passing secrets via standard build ENV instructions is also insecure because environment variables remain visible via docker inspect.
Best Practices:
Docker Secrets: In Docker Swarm mode, secrets are encrypted in transit and at rest, then mounted into container memory (/run/secrets/) as temporary tmpfs files.
External Vault Integration: Fetch secrets dynamically at runtime from key-vault systems (like HashiCorp Vault, AWS Secrets Manager) using secure IAM tokens.
6. How do you debug a crash-looping container?
Start with docker logs <container> to see what it printed right before dying. If it's exiting too fast to catch anything useful, docker inspect <container> shows the exit code, which often hints at the cause (137 usually means OOM-killed, for instance). You can also override the entrypoint to drop into a shell instead of running the app by docker run -it --entrypoint /bin/sh myimage, so you can poke around the filesystem and configure manually. docker events is handy too if you want to watch container state changes in real time as it keeps restarting.
If you want to troubleshoot, follow this sequence :
1# 1. Check exit codes and exact status
2docker ps -a
3
4# 2. Inspect application logs right before failure
5docker logs --tail 200 <container_id>
6
7# 3. Inspect detailed container metadata (environment variables, mounts, health state)
8docker inspect <container_id>
9
10# 4. Override entrypoint to launch an interactive shell and debug filesystem state
11docker run -it --entrypoint /bin/sh <image_name>7. What is Docker Swarm, and how does it compare to Kubernetes?
Docker Swarm: Docker’s built-in orchestration tool. Uses native Docker CLI commands, requires minimal configuration, and handles small-to-medium container clustering easily. It basically turns a group of Docker hosts into one cooperating cluster, with built-in load balancing and service scaling service, all through the same Docker CLI you already know. It's genuinely simple to get running.
Kubernetes (K8s): An enterprise-grade, highly complex orchestration engine created by Google. Handles massive automated scaling, auto-healing, intricate networking policies, complex storage management, and deployment strategies across thousands of nodes. It is a heavier, more feature-rich option.
8. How do you optimize Docker containers for high-concurrency production workloads?
A few things tend to matter most in practice:
keep images small and startup fast so scaling up under load isn't sluggish
set sensible CPU/memory limits and requests so containers aren't starving each other or getting OOM-killed under pressure
tune the app itself for concurrency (connection pool sizes, worker/thread counts appropriate to the container's actual CPU allocation, not the host's)
The practices you can do for managing high concurrency production workloads :
Tune Host Kernel Sysctls: Increase ephemeral port ranges and maximum connection queues (net.core.somaxconn = 1024 or higher).
Increase File Descriptors: Adjust host and container soft/hard ulimits so web servers can maintain thousands of concurrent open socket connections (--ulimit nofile=65535:65535).
Log Management: Configure Docker’s logging driver (json-file or loki) with size rotations (max-size="10m", max-file="3"). Without this, continuous logging can saturate disk space and degrade kernel IOPS under heavy load
Resource Reservations: Set both resource limits and resource requests so the OS scheduler guarantees CPU and memory capacity to high-traffic services.
Related Articles
React JS
Prepare for your React interview with the most asked questions for freshers and experienced developers. Covers hooks, lifecycle, performance optimization, and real-world scenarios.
FrontendJavaScript
Prepare for your next tech interview with the most asked JavaScript interview questions and answers. It includes basic to advanced concepts, coding problems, and real-world scenarios for freshers and experienced developers.