Version 1

Current

Created 7 days ago

Changelog

Initial version

Skill Content

# Docker Multistage > Optimize Docker builds with multi-stage builds You are a Docker optimization expert. The user wants to implement multi-stage builds to reduce final image size and optimize Docker build performance. ## What to check first - Run `docker --version` to confirm Docker is installed (v17.05+) - Check your current Dockerfile with `cat Dockerfile` to identify build artifacts that could be removed - Run `docker images` to see current image sizes before optimization ## Steps 1. Create a new `Dockerfile` with multiple `FROM` statements—each `FROM` starts a new build stage 2. In the first stage (builder), install build tools and compile/transpile your application 3. Use `COPY --from=<stage>` to copy only compiled artifacts from the builder stage to the final stage 4. In the final stage, use a minimal base image (alpine, distroless, or scratch) with only runtime dependencies 5. Add labels and metadata in the final stage with `LABEL` instructions 6. Build with `docker build -t myapp:latest .` and inspect the resulting image size 7. Compare file sizes using `docker history myapp:latest` to verify build artifacts were stripped 8. Push to registry or run with `docker run myapp:latest` ## Code ```dockerfile # Stage 1: Builder FROM node:18-alpine AS builder WORKDIR /build # Install build dependencies RUN apk add --no-cache python3 make g++ # Copy source and package files COPY package*.json ./ RUN npm ci --only=production && npm run build # Stage 2: Runtime FROM node:18-alpine WORKDIR /app # Add security labels LABEL maintainer="[email protected]" LABEL description="Optimized Node.js app with multi-stage build" # Copy runtime dependencies and built artifacts from builder COPY --from=builder /build/node_modules ./node_modules COPY --from=builder /build/dist ./dist COPY --from=builder /build/package.json . # Non-root user for security RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001 USER nodejs # Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD node -e "require('http').get('http://localhost:3000/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})" EXPOSE 3000 CMD ["node", "dist/index.js"] ``` ## Pitfalls - **Forgetting to exclude node_modules from builder stage**: Use `.dockerignore` with `node_modules` and `dist` to prevent copying unnecessary files into the builder layer - **Using outdated base images**: Alpine is lightweight but may have glibc compatibility issues; use `node:18-alpine` for Node or distroless images for production - **Not specifying exact stage name in COPY --from**: If you reference a stage, use the exact name after ## Common Pitfalls - Treating this skill as a one-shot solution — most workflows need iteration and verification - Skipping the verification steps — you don't know it worked until you measure - Applying this skill without understanding the underlying problem — read the related docs first ## When NOT to Use This Skill - When a simpler manual approach would take less than 10 minutes - On critical production systems without testing in staging first - When you don't have permission or authorization to make these changes ## How to Verify It Worked - Run the verification steps documented above - Compare the output against your expected baseline - Check logs for any warnings or errors — silent failures are the worst kind ## Production Considerations - Test in staging before deploying to production - Have a rollback plan — every change should be reversible - Monitor the affected systems for at least 24 hours after the change --- *From [CLSkills.in](https://clskills.in/browse) — 2,300+ free Claude Code skills*