| name | docker |
| title | Docker |
| category | Infra & CI/CD |
| description | Use to containerize an app with a Dockerfile — small, secure, cache-friendly images via multi-stage builds — and build/run/push them. |
| tags | ["docker","containers","dockerfile","multi-stage","images","devops"] |
| official_docs | https://docs.docker.com |
| sources | ["https://docs.docker.com/build/building/best-practices/"] |
| last_verified | 2026-08-10T00:00:00.000Z |
Docker — Skillship
Package an app and its dependencies into a portable image that runs the same everywhere. The goal
is a small, secure, cache-friendly image via multi-stage builds and a slim runtime base.
🧭 When to use this skill
- Use when: you need reproducible builds/deploys across machines, CI, and hosts (Fly/Railway/Render/K8s).
- Use when: your app has native deps or a specific runtime you want to pin.
- Don't use for: static frontends that a CDN host builds for you (usually unnecessary overhead).
⚡ Quickstart
1. Multi-stage Dockerfile (Node example)
# syntax=docker/dockerfile:1
# ---- build stage (has dev deps + toolchain) ----
FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci # copy manifests first so this layer caches until deps change
COPY . .
RUN npm run build
# ---- runtime stage (slim, prod-only) ----
FROM node:22-slim AS runtime
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=build /app/dist ./dist
USER node # run as non-root
EXPOSE 3000
CMD ["node", "dist/server.js"] # exec form so the app is PID 1 and receives signals
2. .dockerignore (keep the build context small)
node_modules
.git
.env
dist
**/*.md
3. Build & run
docker build -t my-app:1.0.0 .
docker run --rm -p 3000:3000 --env-file .env my-app:1.0.0
🧩 Common recipes
Recipe: Pin the base image (reproducible builds)
FROM alpine:3.21@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c
Recipe: Install OS packages cleanly (Debian/Ubuntu)
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*
Recipe: Pass build-time secrets without baking them in
RUN --mount=type=secret,id=npmtoken \
NPM_TOKEN=$(cat /run/secrets/npmtoken) npm ci
docker build --secret id=npmtoken,src=./.npmtoken -t my-app .
Recipe: Fresh build (bypass cache / pull latest base)
docker build --pull --no-cache -t my-app:1.0.0 .
🚀 Ship to production
🔐 Security & secrets
- Never
COPY .env or hardcode credentials — they persist in image layers even if later "removed".
- Prefer official/verified minimal base images; smaller image = smaller attack surface.
- Drop privileges with
USER; avoid sudo inside images.
🐛 Common errors & fixes
| Symptom | Likely cause | Fix |
|---|
| Every build reinstalls deps | COPY . . before installing | Copy package*.json first, then RUN npm ci, then copy source |
| Huge image size | Build tools in final stage | Use multi-stage; copy only artifacts into a slim runtime |
| App ignores Ctrl+C / SIGTERM | Shell-form CMD (not PID 1) | Use exec form: CMD ["node","server.js"] |
| Secret leaked in image | COPY/ENV of secret | Inject at runtime or use build secrets mount |
| Stale packages after edit | apt-get update cached separately | Combine update && install in one RUN |
📚 Sources