Interview Q&A Docker All Levels

Docker Interview Questions & Answers Part 02

40+ Docker interview questions and answers covering architecture, Dockerfile, networking, security, and troubleshooting — Basic to Advanced.

April 26, 2025 19 min read 27 Questions DB
27 Total Questions
13 Basic
12 Intermediate
2 Advanced
Level:
Q1
What is Docker and why is it used?
Basic

Ans:

Docker is a platform for building, shipping, and running applications inside containers — lightweight, isolated environments that package the application with all its dependencies.

Why Docker?

  • Consistency — “Works on my machine” problem solved. Same container runs everywhere.
  • Isolation — Each container has its own filesystem, network, and process space
  • Portability — Run on any OS that has Docker installed
  • Efficiency — Containers share the host OS kernel (unlike VMs with full OS copies)
  • Speed — Containers start in milliseconds
# Run a container
docker run -d -p 80:80 --name webserver nginx

# Check running containers
docker ps

# Check all containers (including stopped)
docker ps -a
Q2
What is the difference between Docker and Virtual Machines?
Basic

Ans:

FeatureDocker ContainerVirtual Machine
OSShares host OS kernelFull guest OS
SizeMBsGBs
StartupMillisecondsMinutes
IsolationProcess-levelHardware-level
PortabilityHighLower
PerformanceNear-nativeOverhead from hypervisor
Use caseMicroservices, appsFull OS environments
VM Architecture:              Docker Architecture:
┌──────────────────┐          ┌──────────────────┐
│  App A  │ App B  │          │  App A  │ App B  │
│  Libs   │ Libs   │          │  Libs   │ Libs   │
│ Guest OS│ Guest OS│         │──────────────────│
│──────────────────│          │   Docker Engine   │
│    Hypervisor    │          │──────────────────│
│─────────────────-│          │    Host OS        │
│     Host OS      │          │──────────────────│
│    Hardware      │          │    Hardware       │
└──────────────────┘          └──────────────────┘
Q3
Explain Docker architecture?
Basic

Ans:

Docker uses a client-server architecture:

Docker CLI (client)
      │  REST API
      ▼
Docker Daemon (dockerd) ← server running on host
      │
      ├── Images
      ├── Containers
      ├── Networks
      └── Volumes

Key components:

ComponentRole
Docker Client (docker CLI)Sends commands to Docker daemon
Docker Daemon (dockerd)Manages containers, images, networks, volumes
Docker ImagesRead-only templates used to create containers
Docker ContainersRunning instances of images
Docker RegistryStores and distributes images (Docker Hub, ECR, etc.)
Docker NetworksIsolated networking for containers
Docker VolumesPersistent storage for containers
# Client sends command to daemon
docker run nginx
# Docker client → API call → dockerd → pulls nginx image → creates container
Q4
What is the use and purpose of a Dockerfile?
Basic

Ans:

A Dockerfile is a text file containing instructions to build a Docker image. It automates the image creation process.

Why use Dockerfile:

  • Reproducible builds — same Dockerfile = same image every time
  • Version-controlled — stored in Git alongside code
  • Automation — builds are scripted, not manual
# Basic Dockerfile example
FROM node:18-alpine          # Base image
WORKDIR /app                 # Set working directory
COPY package*.json ./        # Copy dependency files
RUN npm install              # Install dependencies
COPY . .                     # Copy application code
EXPOSE 3000                  # Document port
CMD ["node", "server.js"]    # Default command to run
# Build image from Dockerfile
docker build -t myapp:1.0 .

# Build with no cache
docker build --no-cache -t myapp:1.0 .
Q5
What are Dockerfile instructions? Explain key ones.
Basic

Ans:

InstructionPurpose
FROMBase image to build on
RUNExecute commands during build (creates a layer)
CMDDefault command when container starts (can be overridden)
ENTRYPOINTMain process; CMD becomes its arguments
COPYCopy files from host to image
ADDLike COPY, but also extracts tarballs and supports URLs
EXPOSEDocuments which port the app listens on
ENVSet environment variables
ARGBuild-time variables
WORKDIRSet working directory
USERSet user to run as
VOLUMECreate a mount point
LABELAdd metadata
HEALTHCHECKDefine health check command
FROM ubuntu:22.04
LABEL maintainer="dev@example.com"
ARG APP_VERSION=1.0
ENV APP_ENV=production
WORKDIR /app
COPY . .
RUN apt-get update && apt-get install -y python3
EXPOSE 8080
USER appuser
HEALTHCHECK --interval=30s CMD curl -f http://localhost:8080/health
ENTRYPOINT ["python3"]
CMD ["app.py"]
Q6
Difference between CMD, ENTRYPOINT, and RUN in Docker.
Basic

Ans:

InstructionWhen it runsPurposeOverridable?
RUNBuild timeExecute commands to build the image (install packages, etc.)N/A
CMDRuntimeDefault arguments/command when container startsYes (docker run img custom-cmd)
ENTRYPOINTRuntimeFixed main process of the containerOnly with --entrypoint flag

Practical example:

FROM nginx
RUN apt-get update && apt-get install -y curl   # Build time only

ENTRYPOINT ["nginx"]         # Always runs nginx
CMD ["-g", "daemon off;"]    # Default args (can be overridden)
# CMD can be overridden:
docker run myimage echo "hello"   # Overrides CMD

# ENTRYPOINT stays, CMD becomes args:
docker run myimage -c /etc/nginx/nginx.conf   # "-c ..." overrides CMD only
Q7
What are main Docker network types?
Basic

Ans:

NetworkDescriptionUse Case
bridgeDefault. Containers get private IPs, communicate via bridge interfaceSame-host container communication
hostContainer uses host’s network namespace directlyHigh performance, no port mapping needed
noneNo network interface. Complete isolationSecurity-sensitive containers
overlayMulti-host networking (Docker Swarm/K8s)Distributed apps across nodes
macvlanContainer gets its own MAC/IP on physical networkLegacy apps expecting direct network access
# List networks
docker network ls

# Create custom bridge network
docker network create --driver bridge mynetwork

# Run container on custom network
docker run -d --network mynetwork --name app nginx

# Inspect network
docker network inspect mynetwork

# On same network, containers can resolve each other by name:
docker run -it --network mynetwork alpine ping app
Q8
If a Docker image is built and you manually install missing packages inside a container, how do you convert it into a new Docker image?
Intermediate

Ans:

# Step 1: Find the running container ID
docker ps

# Step 2: Run the container and install packages
docker exec -it <container_id> bash
apt-get install -y curl vim

# Step 3: Commit the container to a new image
docker commit <container_id> myimage:v2

# With author and message:
docker commit \
  --author "Dev Team" \
  --message "Added curl and vim" \
  <container_id> myimage:v2

# Verify the new image
docker images | grep myimage
docker run myimage:v2 which curl   # Test curl is available

# Step 4 (Best Practice): Update your Dockerfile instead!
# RUN apt-get install -y curl vim
# docker build -t myimage:v2 .

Note: docker commit is useful for quick fixes but should always be followed by updating the Dockerfile for reproducibility.

Q9
One of your containers keeps restarting in production. How do you identify the root cause?
Intermediate

Ans:

# Step 1: Check restart count and status
docker ps -a
# Look at RESTARTS column and STATUS

# Step 2: Check container logs (recent entries)
docker logs <container_name>

# Step 3: Check logs with timestamps
docker logs --timestamps <container_name>

# Step 4: Follow logs in real-time during restart
docker logs -f <container_name>

# Step 5: Check exit code
docker inspect <container_name> \
  --format '{{.State.ExitCode}} {{.State.Error}}'
# Exit 1 = app error, 137 = OOMKilled, 139 = segfault, 143 = SIGTERM

# Step 6: Check events
docker events --filter container=<container_name>

# Step 7: Check resource constraints
docker stats <container_name>

# Step 8: Check inside the container
docker exec -it <container_name> sh

Common causes:

  • Application crash (check exit code 1 → app logs)
  • OOMKilled (exit code 137 → increase memory limit)
  • Port already in use
  • Missing environment variables or config
Q10
How do you optimize Docker image size?
Intermediate

Ans:

# Tip 1: Use slim/alpine base images
FROM node:18-alpine     # 180MB vs FROM node:18 → 1.1GB

# Tip 2: Multi-stage builds (build in one stage, copy only artifacts)
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
# Final image only contains built files + nginx, no node_modules

# Tip 3: Combine RUN commands (each RUN = one layer)
# BAD (3 layers):
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

# GOOD (1 layer):
RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*

# Tip 4: Use .dockerignore
echo "node_modules\n.git\n*.log\ndist" > .dockerignore

# Tip 5: Don't copy unnecessary files
COPY src/ ./src/   # Instead of COPY . .
# Check image size
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"

# Analyze layers
docker history myimage:1.0
Q11
How do you scan Docker images for vulnerabilities before deployment?
Intermediate

Ans:

# Method 1: Docker Scout (built into Docker CLI)
docker scout cves myimage:1.0
docker scout recommendations myimage:1.0

# Method 2: Trivy (most popular, free, open-source)
# Install
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh

# Scan image
trivy image myimage:1.0

# Scan with specific severity
trivy image --severity HIGH,CRITICAL myimage:1.0

# Output as JSON for CI/CD
trivy image --format json -o results.json myimage:1.0

# Method 3: Snyk
snyk container test myimage:1.0

# Method 4: AWS ECR Scan (if using ECR)
aws ecr start-image-scan \
  --repository-name my-repo \
  --image-id imageTag=1.0

aws ecr describe-image-scan-findings \
  --repository-name my-repo \
  --image-id imageTag=1.0

# Integrate into CI/CD pipeline (Jenkins/GitHub Actions):
# Run trivy after docker build, fail pipeline if CRITICAL vulns found
trivy image --exit-code 1 --severity CRITICAL myimage:1.0
Q12
How would you manage secrets in Docker containers securely?
Intermediate

Ans:

# BAD (Never do this):
ENV DB_PASSWORD=mysecret123          # Visible in image layers
docker run -e DB_PASSWORD=mysecret   # Visible in docker inspect

# Method 1: Docker Secrets (Docker Swarm)
echo "mysecret" | docker secret create db_password -
docker service create \
  --secret db_password \
  --name myapp myimage
# Secret available at: /run/secrets/db_password inside container

# Method 2: Environment variables from a file (for compose)
# .env file (not committed to git):
DB_PASSWORD=mysecret123

# docker-compose.yml:
# env_file:
#   - .env

# Method 3: AWS Secrets Manager / SSM at runtime
# In entrypoint script:
export DB_PASSWORD=$(aws secretsmanager get-secret-value \
  --secret-id prod/db-password \
  --query SecretString --output text)

# Method 4: Vault (HashiCorp) Agent Sidecar
# Vault agent auto-renews and injects secrets into container

# Method 5: Kubernetes Secrets (when in K8s)
kubectl create secret generic db-secret --from-literal=password=mysecret
# Mount as volume or envFrom in pod spec
Q13
How do you handle a vulnerable dependency detected in a Docker image after deployment?
Advanced

Ans:

# Immediate mitigation:

# Step 1: Confirm and assess the vulnerability
trivy image myimage:1.0 --severity CRITICAL

# Step 2: Check if the vulnerable package is actually used
docker run myimage:1.0 dpkg -l | grep <package-name>

# Step 3: If critical — isolate/rollback immediately
# Kubernetes rollback:
kubectl rollout undo deployment/myapp

# Docker Swarm rollback:
docker service rollback myapp-service

# Step 4: Fix the vulnerability
# Update base image:
# FROM node:18-alpine → FROM node:18.20-alpine (patched version)

# Update specific package:
RUN apt-get update && apt-get install -y --only-upgrade <vulnerable-package>

# Step 5: Rebuild and rescan
docker build -t myimage:1.1 .
trivy image --exit-code 1 --severity CRITICAL myimage:1.1

# Step 6: Secure the CI/CD pipeline going forward
# - Add trivy scan gate in Jenkins/GitHub Actions
# - Set up automated base image update PRs (Renovate/Dependabot)
# - Schedule weekly image rescans even for deployed images
Q14
What is containerization?
Basic

Ans:

Containerization is the process of packaging an application and all its dependencies (code, runtime, libraries, config) into a single portable unit called a container.

How it works:

  • Uses Linux kernel features: namespaces (isolation) and cgroups (resource limits)
  • Containers share the host OS kernel — no Guest OS overhead
  • Each container has its own: filesystem, network stack, process tree
# Namespaces used:
# PID namespace → isolated process IDs
# NET namespace → isolated networking
# MNT namespace → isolated filesystem
# UTS namespace → isolated hostname
# IPC namespace → isolated inter-process communication
# USER namespace → isolated user IDs

# cgroups control:
# CPU usage
# Memory limits
# I/O bandwidth

Benefits: Consistency, portability, density (many containers per host), fast startup.

Q15
How do you verify deployed app files on an EC2 container host?
Basic

Ans:

# Check running containers
docker ps

# Inspect container details (image, mounts, env)
docker inspect <container_name>

# Access container filesystem
docker exec -it <container_name> sh
ls -la /app/
cat /app/config.json

# Check mounted volumes
docker inspect <container_name> \
  --format '{{json .Mounts}}' | python3 -m json.tool

# Copy file from container to host for inspection
docker cp <container_name>:/app/config.json /tmp/config.json

# Check image that the container is running
docker inspect <container_name> --format '{{.Config.Image}}'

# Check container logs for startup output
docker logs <container_name> --tail 50
Q16
How do you clear old build artifacts before deployment?
Intermediate

Ans:

# Remove stopped containers
docker container prune -f

# Remove dangling images (untagged, not used)
docker image prune -f

# Remove all unused images (not just dangling)
docker image prune -a -f

# Remove unused volumes
docker volume prune -f

# Remove unused networks
docker network prune -f

# Nuclear option — remove everything unused
docker system prune -a -f --volumes

# Check disk usage before/after
docker system df

# In Jenkins pipeline — clean before build:
pipeline {
  stages {
    stage('Clean') {
      steps {
        sh 'docker system prune -f'
        sh 'docker rmi myapp:old || true'
      }
    }
  }
}
Q17
What is the difference between docker stop and docker kill?
Basic

Ans:

CommandSignal sentBehavior
docker stopSIGTERM, then SIGKILL after timeoutGraceful shutdown. App can clean up.
docker killSIGKILL by defaultImmediate force kill. No cleanup.
# Graceful stop (allows 10s for cleanup by default)
docker stop mycontainer

# Graceful stop with custom timeout
docker stop --time 30 mycontainer

# Force kill immediately
docker kill mycontainer

# Send specific signal
docker kill --signal SIGHUP mycontainer

Best practice: Always use docker stop first. Use docker kill only if the container is unresponsive.

Q18
How do you validate environment variables for app startup in Docker?
Intermediate

Ans:

# Method 1: Check env vars inside running container
docker exec mycontainer env
docker exec mycontainer printenv DB_HOST

# Method 2: Inspect from outside
docker inspect mycontainer --format '{{json .Config.Env}}'

# Method 3: Validate at entrypoint script level
#!/bin/bash
# entrypoint.sh
required_vars=("DB_HOST" "DB_PORT" "APP_SECRET")
for var in "${required_vars[@]}"; do
  if [ -z "${!var}" ]; then
    echo "ERROR: Required env var $var is not set"
    exit 1
  fi
done
exec "$@"

# Dockerfile:
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["node", "server.js"]

# Method 4: Docker Compose env validation
# Pass from .env file and validate with compose healthcheck
Q19
How do you roll back a failed Docker deployment?
Intermediate

Ans:

# Method 1: Docker (standalone) — switch back to previous image tag
docker stop myapp
docker rm myapp
docker run -d --name myapp myimage:1.0   # Previous version

# Method 2: Docker Compose
# Revert docker-compose.yml to old image version
# image: myapp:1.0 (instead of 1.1)
docker-compose up -d

# Method 3: Docker Swarm
docker service rollback myapp-service
# Or update to previous image:
docker service update --image myimage:1.0 myapp-service

# Method 4: Kubernetes (if using K8s)
kubectl rollout undo deployment/myapp
kubectl rollout undo deployment/myapp --to-revision=3   # Specific revision

# Method 5: Scripted rollback
PREV_IMAGE=$(docker inspect myapp --format '{{.Config.Image}}')
# Store previous image tag in a file or environment variable before each deploy
docker stop myapp && docker rm myapp
docker run -d --name myapp $PREV_IMAGE

Best practice: Always tag images with version numbers, never just latest in production.

Q20
What is a multi-stage Dockerfile and when do you use it?
Intermediate

Ans:

A multi-stage build uses multiple FROM statements in a single Dockerfile to produce a minimal final image by copying only the necessary artifacts from build stages.

Use case: Compile/build in a fat image, ship only the binary in a slim image.

# Stage 1: Build (uses full Go/Node/Maven image)
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp ./cmd/

# Stage 2: Final image (tiny, secure)
FROM alpine:3.18
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
# Build
docker build -t myapp:1.0 .

# Result: Final image is ~15MB instead of ~800MB
docker images myapp

Benefits:

  • No build tools (gcc, npm, go) in production image
  • Smaller attack surface
  • Faster image pulls
Q21
What is the difference between Docker and Kubernetes?
Basic

Ans:

They’re not competitors — they operate at different layers and are almost always used together:

AspectDockerKubernetes
What it isContainer runtime — builds and runs a single containerContainer orchestrator — manages many containers across many machines
ScopeOne hostA cluster of many hosts (nodes)
HandlesBuilding images, running/stopping containersScheduling, scaling, self-healing, networking, rolling updates across the whole fleet
Failure recoveryNone built-in — if a container dies, it stays deadAutomatically restarts/reschedules failed containers (Pods)
ScalingManual (docker run more containers)Declarative and automatic (Deployments, HPA)
Networking across hostsNot handledBuilt-in cluster networking (Services, DNS)
Docker: "How do I package and run this one application?"
Kubernetes: "How do I run 200 containers across 50 servers,
             keep them healthy, and route traffic to them?"

How they fit together:

Developer writes Dockerfile → docker build → image pushed to registry (ECR)
                                                      │
Kubernetes Deployment references that image ──────────┘
kubectl reads the Deployment → schedules Pods (running that image) across nodes
→ restarts them if they crash, scales them under load, load-balances traffic via Services

Note: Kubernetes no longer uses dockerd directly as its container runtime (deprecated via dockershim in 1.24+) — it now uses containerd or CRI-O directly. You can still build images with the docker CLI; Kubernetes just doesn’t depend on the Docker daemon to run them anymore.

Q22
Write a sample multi-stage Dockerfile.
Intermediate

Ans:

Here’s a multi-stage build for a React frontend, served by nginx — the ~1GB of build tooling never reaches the final image:

# Stage 1: Build — full Node toolchain, only exists during build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci                     # reproducible install from package-lock.json
COPY . .
RUN npm run build              # outputs static files to /app/build

# Stage 2: Serve — tiny final image, no Node/npm at all
FROM nginx:1.25-alpine AS final
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s CMD wget -q --spider http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
docker build -t frontend:1.0 .
docker images frontend
# builder stage: ~450MB (node_modules + build tools)
# final image:   ~25MB  (just nginx + static files)
Q23
Explain how a multi-stage Dockerfile helps optimize image size.
Intermediate

Ans:

Without multi-stage builds, everything needed to build the app ends up baked into the same image you ship — compilers, package managers, source code, test files, dev dependencies — even though none of that is needed at runtime.

How multi-stage builds fix this:

Single-stage (bloated):                Multi-stage (optimized):
┌─────────────────────┐                ┌──────────┐      ┌─────────────────┐
│ gcc, npm, go, git    │                │ Build    │      │ Final            │
│ node_modules/        │   copy only    │ Stage    │ ───▶ │ - compiled binary│
│ source code           │   final       │ (fat,    │      │ - or built assets│
│ compiled output       │   artifact    │ discarded)│      │ (slim, shipped)  │
└─────────────────────┘                └──────────┘      └─────────────────┘

Mechanism: each FROM starts a brand-new, independent build stage. The COPY --from=<stage> instruction pulls only the specific files you name from an earlier stage into the current one — every layer from the build stage (package caches, compilers, intermediate files) is discarded because it’s never referenced by the final stage.

Why this matters beyond just disk space:

  • Smaller attack surface — no compilers or package managers in production means fewer tools available to an attacker who gains shell access
  • Faster deploys — smaller images pull and start faster, especially important for autoscaling and cold starts
  • Faster CI — less data to push/pull from the registry on every build

This is different from just adding a .dockerignore or using apt-get remove after install (which still leaves traces in earlier layers) — multi-stage builds physically never copy the unwanted layers into the final image at all.

Q24
What are CVEs (Common Vulnerabilities and Exposures)?
Basic

Ans:

A CVE is a publicly disclosed, uniquely-identified security vulnerability in software or a dependency, catalogued in a shared database maintained by MITRE and the NVD (National Vulnerability Database).

Anatomy of a CVE ID:

CVE-2024-3094
 │    │    │
 │    │    └── Sequence number for that year
 │    └─────── Year the CVE was assigned/disclosed
 └──────────── Fixed prefix

Why they matter for containers: a Docker image is a stack of layers — base OS packages, language runtime, and your app’s dependencies — and a CVE in any of them (even a transitive dependency you never directly installed) is a CVE in your image.

Severity is scored via CVSS (0–10):

ScoreSeverity
9.0–10.0Critical
7.0–8.9High
4.0–6.9Medium
0.1–3.9Low

A CVE existing doesn’t automatically mean you’re exploitable — whether the vulnerable code path is actually reachable in your app matters, which is why scanners increasingly try to flag reachable vulnerabilities, not just “package X version Y is present.”

Q25
Which CVEs have you encountered in production, and how did you remediate them?
Advanced

Ans:

This is an experience question — interviewers want to see your remediation process, not memorized CVE numbers. A strong structure:

Example walkthrough: “Our Trivy scan in CI flagged CVE-2023-44487 (the ‘HTTP/2 Rapid Reset’ DoS vulnerability) as CRITICAL in a base image we were using.”

# 1. Confirm exposure — is the vulnerable component actually in use?
trivy image --severity CRITICAL myimage:1.0
docker run myimage:1.0 dpkg -l | grep <affected-package>

# 2. Check for an available patched version
trivy image myimage:1.0 --format json | jq '.Results[].Vulnerabilities[] | select(.VulnerabilityID=="CVE-2023-44487")'

# 3. Immediate mitigation while a fix is prepared (if internet-facing and unpatched)
# e.g., rate-limit at the load balancer / WAF layer

# 4. Permanent fix — bump the base image / package to the patched version
# FROM node:18.17-alpine  →  FROM node:18.18-alpine

# 5. Rebuild, rescan, verify clean
docker build -t myimage:1.1 .
trivy image --exit-code 1 --severity CRITICAL myimage:1.1

# 6. Roll out via normal pipeline (not a manual hotfix) so it's tracked and repeatable

Lesson to highlight: the recurring theme across most production CVEs isn’t zero-days — it’s stale base images. The fix that actually prevents recurrence is usually automated dependency update PRs (Renovate/Dependabot) plus a CI gate that fails the build on CRITICAL findings, not a one-off manual patch.

Q26
Name at least five tools used to identify or remediate CVEs.
Basic

Ans:

ToolTypeNotes
TrivyImage/filesystem/IaC scannerFree, open-source, most widely used in CI pipelines
GrypeImage/filesystem scannerAnchore’s open-source scanner, fast, SBOM-aware
SnykDependency + container scannerCommercial, strong IDE/PR integration, auto-fix PRs
Docker ScoutImage scannerBuilt into the Docker CLI (docker scout cves)
AWS ECR Image ScanningRegistry-native scannerRuns automatically on push if enabled on the repo
ClairStatic analysis scannerUsed by Quay and other registries
OWASP Dependency-CheckDependency scannerFocused on application-level libraries (Java, .NET, Node)
Dependabot / RenovateRemediation (not detection)Auto-opens PRs to bump vulnerable dependencies

In a typical pipeline you’d pair a detection tool (Trivy/Grype scanning every build) with a remediation tool (Renovate/Dependabot opening the fix PRs automatically) so the loop from “CVE published” to “patched in production” doesn’t rely on someone manually noticing.

Q27
Which Docker base image did you use for your application and why?
Intermediate

Ans:

This is meant as an experience question — interviewers want your reasoning, not just a name. A strong answer walks through the trade-off:

Example answer: “For a Node.js API, I used node:18-alpine as the runtime stage base image.”

Why alpine over the full/slim variants:

Base imageSizeNotes
node:18~1.1 GBFull Debian — includes build tools, docs, many packages you’ll never use
node:18-slim~200 MBDebian, stripped of most non-essential packages
node:18-alpine~180 MBmusl libc + BusyBox instead of glibc — smallest option
gcr.io/distroless/nodejs18~150 MBNo shell, no package manager at all — max security, harder to debug

Trade-offs I considered:

  • Alpine’s musl libc occasionally causes subtle compatibility issues with native Node modules compiled against glibc — worth testing, not just assuming it “just works”
  • Distroless is even smaller and more secure (no shell = smaller attack surface if compromised) but makes kubectl exec debugging much harder since there’s no shell to exec into — I chose alpine as the practical middle ground since we still needed occasional interactive debugging in staging
  • For a build stage (not the final image), I used the full node:18 image since it needs the complete toolchain — multi-stage build discards it afterward, so its size doesn’t matter

What good answers avoid: picking latest (unpinned, unpredictable) or the largest/full image “because it’s safer” without weighing the size/attack-surface cost — the interviewer is checking whether you actively evaluated the trade-off rather than defaulting to whatever the tutorial used.

Add More Questions to This Guide

Know a question that should be here? Share it and help the community!

Open Google Form