Docker — Advanced Questions and Answers

Beginner | Intermediate | Advanced | Docker Compose

1. What are multi-stage builds and why do they matter?

A multi-stage build uses several FROM blocks in one Dockerfile: heavy "builder" stages compile and produce artifacts, and a lightweight final stage copies only the artifacts. Build tools, compilers, caches, and test dependencies never reach the shipped image — making it smaller and reducing the attack surface.

# ---- Stage 1: build ----
FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# ---- Stage 2: runtime ----
FROM node:20-slim
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
USER node
CMD ["node", "dist/server.js"]

Notes:

2. How do I analyze and shrink an image?

docker image ls                          # sizes at a glance
docker history my-api:1.0                # size contributed by each layer
docker buildx build --sbom=true .        # SBOM (with BuildKit)
# interactive layer-by-layer exploration:
# dive my-api:1.0   (github.com/wagoodman/dive)

Shrinking techniques, in order of impact:

3. How do I scan images for vulnerabilities?

Treat images as dependencies: scan them continuously in CI and on schedule.

docker scout cves my-api:1.0        # Docker Scout (built into Docker Desktop)
trivy image my-api:1.0              # Trivy — very common in CI pipelines
grype my-api:1.0                    # Grype (Anchore)

4. How do I run containers securely (least privilege)?

5. How should I handle secrets?

Rules of thumb: never COPY secrets into images, never put them in ENV/ARG (they persist in image metadata and docker history), and never commit them. Options:

# Build-time secret via BuildKit — never stored in a layer:
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci
# docker build --secret id=npm_token,src=.npmrc .

6. How do private registries work?

# Self-hosted registry (with basic auth via reverse proxy or htpasswd):
docker run -d -p 5000:5000 --restart always --name registry registry:2

# Cloud registries: AWS ECR, Azure ACR, Google GAR/Artifact Registry
docker login myregistry.corp.com
docker tag my-api:1.0 myregistry.corp.com/team/my-api:1.0
docker push myregistry.corp.com/team/my-api:1.0

7. How does Docker fit into a CI/CD pipeline?

A typical pipeline per commit: build → test (inside containers) → scan → push → deploy.

# GitHub Actions example
- name: Set up Buildx
  uses: docker/setup-buildx-action@v3
- name: Login to registry
  uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
  uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: |
      ghcr.io/org/app:${{ github.sha }}
      ghcr.io/org/app:latest
    cache-from: type=registry,ref=ghcr.io/org/app:cache
    cache-to: type=registry,ref=ghcr.io/org/app:cache,mode=max

8. When do I need orchestration — and which one?

Docker alone manages a single host. You need an orchestrator when you require multi-host scheduling, self-healing, load balancing, rolling deployments, and scaling:

OptionBest forNotes
Docker SwarmSmall clusters, simplicityBuilt into Docker; declining adoption
KubernetesThe de-facto standard at any serious scaleSteep learning curve, huge ecosystem
Managed servicesAWS/Azure workloads without cluster opsECS/EKS/Fargate on AWS, AKS on Azure, GKE on GCP

Related pages in this knowledge base:

9. What exists beyond Docker? (OCI, containerd, Podman)

Images and runtimes are standardized by the Open Container Initiative (OCI): an image spec and a runtime spec. Consequences:

10. Production-readiness checklist for a containerized service

  1. Runs as a non-root user; read-only root filesystem where possible.
  2. Minimal, version-pinned base image (multi-stage if building), scanned with no open Critical/High CVEs.
  3. HEALTHCHECK / readiness endpoint implemented.
  4. Handles SIGTERM gracefully (drain connections; docker stop grace period / stop_grace_period tuned).
  5. Logs to stdout/stderr; logs and metrics collected externally.
  6. Resource limits (--memory, --cpus) and a restart policy set.
  7. State in volumes or external services only — never in the container layer.
  8. Config via environment/secrets, never baked in; secrets rotated, not in image metadata.
  9. Deployed by immutable tag (commit SHA or semver), never latest.
  10. Defined upgrade path: image rebuild cadence to pick up base-image patches.
← Back to IT Knowledge Base