intermediate
Dockerfile
Describe image builds through ordered instructions for base images, dependencies, source files, users, entrypoints, and commands.
A Dockerfile is build code. Instruction order controls caching and correctness: copy manifests first, install with a frozen lockfile, copy source later, build, then set runtime user and command deliberately.
FROM node:20-bookworm-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM deps AS build
COPY . .
RUN npm run build
FROM node:20-bookworm-slim AS runtime
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
USER node
CMD ["node", "dist/server.js"]
Use `.dockerignore` to exclude `node_modules`, `.git`, tests, and local env files. Prefer `COPY` over `ADD` unless you need archive extraction.
On interviews: `COPY` vs `ADD`, `.dockerignore`, non-root users, build args versus runtime env, and separating build-time from runtime configuration.
Common pitfalls: copying the whole repo before `npm ci` destroys cache reuse; secrets in `ARG` or layers leak in image history.
The trade-off is build speed (layer caching) versus clarity and safe separation of build secrets from runtime images.
Checklist:
- Order instructions for cache correctness.
- Use `.dockerignore`.
- Avoid secrets in layers or build args.
- Run production processes as non-root when possible.