docker-developmentlisted
Install: claude install-skill tmj-90/gaffer
# Smaller images. Faster builds. Secure containers.
Opinionated Docker workflow — turn bloated Dockerfiles into production-grade containers. Three concerns: size, speed (build cache), security.
## Multi-stage build pattern (every production image)
```dockerfile
# --- build stage ---
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
# --- runtime stage ---
FROM node:22-alpine AS runtime
RUN addgroup -S app && adduser -S -G app app
WORKDIR /app
COPY --from=build --chown=app:app /app/dist ./dist
COPY --from=build --chown=app:app /app/node_modules ./node_modules
USER app
EXPOSE 3000
CMD ["node", "dist/main.js"]
```
Key principles:
- Build tools and source code stay in the build stage; only the artifact ships.
- Non-root user (`USER app`) in the runtime stage.
- `.dockerignore` excludes `node_modules/`, `.git/`, `*.md`, test files.
## Layer caching discipline
1. Copy dependency manifests first (`package.json`, `pnpm-lock.yaml`) — before source code.
2. Run install — cache busts only on lockfile change.
3. Copy source — cache busts on any source change.
4. Build — always after source copy.
Violating this order invalidates cache on every source change.
## Security hardening
| Control | Implementation |
|---------|---------------|
| Non-root user | `addgroup/adduser` + `USER` directive |
| Read-only filesystem | `--read-only` flag at runtime; explicit tmpfs mounts where