Docker is the foundation of modern application deployment and is expected knowledge for virtually every backend and DevOps engineering role at Indian product companies. Understanding Docker's architecture, Dockerfile best practices, and Docker Compose for multi-service local development is tested in most senior engineering interviews. This guide covers Docker interview questions for India in 2026.
Docker architecture and core concepts
Docker fundamentals:
1. What is Docker? Docker is a platform for building, packaging, and running applications in containers. A container is a lightweight, isolated process that packages an application and its dependencies (libraries, configuration files, environment variables) into a single unit that runs consistently across any environment.
2. Docker components: - Docker Engine: the Docker daemon (dockerd); runs on the host; manages containers, images, networks, and volumes. Accessed via the Docker CLI. - Docker Image: a read-only, layered template for creating containers. Built from a Dockerfile. Stored in a container registry (Docker Hub, ECR, ACR, GCR). - Docker Container: a running instance of a Docker image. Isolated from the host and other containers via Linux namespaces (PID, network, mount, UTS, IPC) and cgroups (CPU and memory limits). - Docker Registry: a server that stores and distributes Docker images. Docker Hub: the public registry. ECR (AWS Elastic Container Registry), ACR (Azure Container Registry): private registries.
3. Docker image layers: A Docker image is a stack of read-only layers. Each instruction in the Dockerfile (FROM, RUN, COPY) creates a new layer. Layers are cached: if a layer's instruction and all preceding layers have not changed, Docker uses the cached layer instead of rebuilding. This makes builds fast when layers that change frequently (COPY source code) come after layers that change infrequently (RUN npm install) — cache is invalidated at the first changed layer and all subsequent layers are rebuilt.
4. Layer cache optimisation: Bad (cache-busting): ```dockerfile COPY . . RUN npm install ``` Every code change invalidates the npm install cache.
Good (cache-friendly): ```dockerfile COPY package*.json ./ RUN npm install COPY . . ``` npm install is cached until package.json changes; source code changes only invalidate the COPY . . layer.
Dockerfile best practices and multi-stage builds
Writing production Dockerfiles:
1. Dockerfile instructions: - FROM: the base image (FROM node:20-alpine; alpine images are smaller) - WORKDIR: sets the working directory inside the container - COPY: copies files from the host into the image (prefer COPY over ADD; ADD has extra features you rarely need) - RUN: executes a command during the build; creates a new layer; combine multiple commands with && to reduce layers - EXPOSE: documents which port the container listens on (does not actually publish the port; use -p or Docker Compose ports to publish) - ENV: sets environment variables in the image - CMD: the default command to run when the container starts; can be overridden at runtime (CMD ['node', 'server.js']) - ENTRYPOINT: the fixed command; CMD provides default arguments to the ENTRYPOINT
2. Multi-stage builds: Multi-stage builds reduce final image size by separating build dependencies from runtime dependencies: ```dockerfile # Stage 1: build FROM node:20 AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build
# Stage 2: production runtime FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/nodemodules ./nodemodules EXPOSE 3000 CMD ['node', 'dist/server.js'] ``` The final image has only the runtime files (no TypeScript compiler, no source maps, no dev dependencies).
3. .dockerignore: Similar to .gitignore; files listed in .dockerignore are not included in the Docker build context. Always exclude: node_modules/, .git/, .env, *.log, dist/, .next/.
Docker Compose and container networking
Docker Compose and networking:
1. Docker Compose: Docker Compose defines and runs multi-container applications. A docker-compose.yml file describes: services (containers), networks, and volumes. docker compose up starts all services; docker compose down stops and removes them.
```yaml services: api: build: . ports: - '3000:3000' environment: - DATABASEURL=postgresql://user:pass@db:5432/mydb dependson: - db db: image: postgres:16-alpine volumes: - postgresdata:/var/lib/postgresql/data environment: - POSTGRESUSER=user - POSTGRESPASSWORD=pass - POSTGRESDB=mydb
volumes: postgres_data: ```
2. Container networking: By default, Docker Compose creates a bridge network for all services in the docker-compose.yml. Services communicate using their service name as the hostname: the API container reaches the database at host db (not localhost). Published ports (-p 3000:3000 or ports: '3000:3000'): maps a container port to a host port; allows external traffic to reach the container.
3. Docker volumes: Volumes persist data outside the container's writable layer. When a container is removed, its writable layer is gone; data in volumes persists. Named volumes (postgres_data: in the example above): managed by Docker; stored in Docker's data directory. Bind mounts: mount a host directory into the container (useful for development: changes to local source files are immediately reflected in the container).
4. Docker Compose for local development: Docker Compose enables one-command setup for complex local environments: a developer runs docker compose up and gets the API, database, Redis, and any other services running locally with the correct configuration. This removes the 'works on my machine' problem for the entire development environment.
Practise Docker and DevOps interview questions with HireStepX's AI voice interviewer. Get scored feedback on your explanations of container architecture, Dockerfile optimisation, and Docker Compose. First 2 sessions free.
Practice freeDocker security, Docker vs VMs, and production patterns
Docker production and security:
1. Docker vs Virtual Machines: VM: complete guest OS (kernel + OS) running on a hypervisor. Heavyweight (GBs), slow to start (minutes), strong isolation (separate kernels). Docker container: shares the host kernel; packages only the application and its runtime dependencies. Lightweight (MBs), starts in seconds, slightly weaker isolation (processes are isolated but share the kernel). Modern production: containers on Kubernetes for microservices; VMs for infrastructure that needs full OS control or stronger isolation (database servers, CI workers).
2. Docker security best practices: - Run as a non-root user: USER node in the Dockerfile (not running as root reduces the blast radius if a vulnerability is exploited) - Use specific image tags: FROM node:20.11.1-alpine, not FROM node:latest (pinning prevents unexpected breaking changes) - Scan images for vulnerabilities: docker scout cves, Trivy, Snyk (scan the image layers for known CVEs) - Do not store secrets in the Dockerfile (use environment variables passed at runtime or Docker Secrets) - Minimal base images: Alpine Linux images are smaller and have fewer pre-installed packages (smaller attack surface)
3. Container orchestration: For running multiple containers in production, Docker Compose is for local development only. Production orchestration: Kubernetes (the industry standard for container orchestration); Amazon ECS (simpler than Kubernetes; used by many Indian companies on AWS); Docker Swarm (simpler than Kubernetes; less widely adopted).
4. Docker in CI/CD: Typical CI/CD pattern: (1) CI pipeline builds the Docker image. (2) CI runs tests inside the container. (3) CI pushes the image to a registry (ECR, ACR, Docker Hub). (4) CD deploys the new image tag to Kubernetes (helm upgrade or kubectl set image).
Frequently asked questions
Explore more