Expert guidance on dockerfile optimization, multi-stage builds, layer caching strategies, and base image selection. Activates when working with "dockerfile", "docker-compose", "multi-stage", "container optimization", "image layers", or "build cache".
/plugin marketplace add Lobbi-Docs/claude/plugin install container-workflow@claude-orchestrationThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Apply industry-standard best practices for building optimized, maintainable, and efficient Docker containers. Master multi-stage builds, layer caching, base image selection, and build optimization strategies to create production-ready container images.
Order Instructions for Maximum Cache Efficiency:
Structure Dockerfile layers from least to most frequently changing:
# 1. Base image (changes rarely)
FROM node:20-alpine AS base
# 2. System dependencies (changes occasionally)
RUN apk add --no-cache \
python3 \
make \
g++
# 3. Working directory setup
WORKDIR /app
# 4. Package manifest files (changes moderately)
COPY package.json package-lock.json ./
# 5. Dependencies installation (leverages cache when manifest unchanged)
RUN npm ci --only=production
# 6. Application code (changes frequently)
COPY . .
# 7. Build step (only when code changes)
RUN npm run build
# 8. Runtime configuration
EXPOSE 3000
CMD ["node", "dist/main.js"]
Combine RUN Commands to Reduce Layers:
Minimize image size by chaining related commands:
# Bad: Creates 3 layers
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean
# Good: Creates 1 layer
RUN apt-get update && \
apt-get install -y curl && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
Use .dockerignore to Exclude Unnecessary Files:
Create .dockerignore to prevent copying build artifacts and sensitive files:
# Development files
node_modules/
npm-debug.log*
.git/
.gitignore
# Test files
*.test.js
coverage/
.nyc_output/
# Documentation
README.md
docs/
# IDE files
.vscode/
.idea/
# Environment files
.env
.env.local
*.key
*.pem
Separate Build and Runtime Environments:
Use multi-stage builds to create minimal production images:
# Stage 1: Build environment with all dev dependencies
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build && \
npm run test
# Stage 2: Production environment with only runtime dependencies
FROM node:20-alpine AS production
WORKDIR /app
# Copy only necessary files from builder
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
# Security: Run as non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 && \
chown -R nodejs:nodejs /app
USER nodejs
EXPOSE 3000
CMD ["node", "dist/main.js"]
Create Specialized Build Targets:
Define multiple targets for different use cases:
# Development stage with hot reload
FROM node:20-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000 9229
CMD ["npm", "run", "dev"]
# Testing stage with test dependencies
FROM development AS testing
RUN npm run lint && \
npm run test:unit && \
npm run test:integration
# Build stage
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage (minimal)
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]
Build specific stages:
# Development
docker build --target development -t myapp:dev .
# Testing
docker build --target testing -t myapp:test .
# Production
docker build --target production -t myapp:prod .
Choose Minimal Base Images:
Select the smallest viable base image for your runtime:
# Python examples by size
FROM python:3.11-alpine # ~50MB (best for simple apps)
FROM python:3.11-slim # ~120MB (good compatibility)
FROM python:3.11 # ~900MB (avoid in production)
# Node.js examples by size
FROM node:20-alpine # ~110MB (best for production)
FROM node:20-slim # ~170MB (good compatibility)
FROM node:20 # ~900MB (avoid in production)
# Distroless images (Google)
FROM gcr.io/distroless/nodejs20-debian12 # Minimal attack surface
FROM gcr.io/distroless/python3-debian12 # No shell, no package manager
Use Distroless for Maximum Security:
Distroless images contain only your application and runtime dependencies:
# Build stage
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Production: Distroless image
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER nonroot:nonroot
EXPOSE 3000
CMD ["dist/main.js"]
Pin Specific Versions:
Always use specific version tags for reproducibility:
# Bad: Version changes unexpectedly
FROM node:20
# Good: Specific version pinned
FROM node:20.11.1-alpine3.19
# Better: Use digest for immutability
FROM node:20.11.1-alpine3.19@sha256:abc123...
Structure for Cache Reuse:
Place frequently changing instructions after stable ones:
FROM python:3.11-slim
# System packages (rarely change)
RUN apt-get update && \
apt-get install -y --no-install-recommends \
postgresql-client && \
apt-get clean
# Requirements (change occasionally)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Application code (changes frequently)
COPY . .
CMD ["python", "app.py"]
Use BuildKit Cache Mounts:
Enable BuildKit for advanced caching:
# syntax=docker/dockerfile:1.4
FROM python:3.11-slim
# Cache pip downloads across builds
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
# Cache apt packages
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/var/lib/apt \
apt-get update && \
apt-get install -y postgresql-client
Build with BuildKit:
DOCKER_BUILDKIT=1 docker build -t myapp:latest .
Implement Layer Caching in CI/CD:
Use registry cache for faster CI builds:
# GitHub Actions with BuildKit cache
docker buildx build \
--cache-from type=registry,ref=ghcr.io/org/app:cache \
--cache-to type=registry,ref=ghcr.io/org/app:cache,mode=max \
--tag ghcr.io/org/app:latest \
--push .
Configure Health Checks:
Define health checks for container orchestration:
FROM node:20-alpine
WORKDIR /app
COPY . .
# HTTP health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
# Alternative: Using curl
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "server.js"]
Set Appropriate Working Directory:
Always use absolute paths for WORKDIR:
# Bad: Relative path
WORKDIR app
# Good: Absolute path
WORKDIR /app
# Better: Clear organization
WORKDIR /opt/application
Use COPY Instead of ADD:
Prefer COPY for clarity unless you need ADD's special features:
# Bad: ADD has implicit behavior (extracts tars, fetches URLs)
ADD archive.tar.gz /app/
# Good: COPY is explicit and predictable
COPY src/ /app/src/
COPY package.json /app/
# OK: ADD when you need tar extraction
ADD rootfs.tar.gz /
Create Environment-Specific Overrides:
Use base compose file with environment overrides:
# docker-compose.yml (base)
version: '3.9'
services:
app:
build:
context: .
dockerfile: Dockerfile
environment:
NODE_ENV: production
restart: unless-stopped
db:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
postgres_data:
# docker-compose.override.yml (development)
version: '3.9'
services:
app:
build:
target: development
volumes:
- .:/app
- /app/node_modules
ports:
- "3000:3000"
- "9229:9229" # Debug port
environment:
NODE_ENV: development
db:
ports:
- "5432:5432"
# docker-compose.prod.yml (production)
version: '3.9'
services:
app:
build:
target: production
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Use with:
# Development (uses docker-compose.override.yml automatically)
docker compose up
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
Control Startup Order:
Use depends_on with health checks:
version: '3.9'
services:
app:
image: myapp:latest
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
Set Memory and CPU Constraints:
Prevent resource exhaustion:
version: '3.9'
services:
app:
image: myapp:latest
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
mem_limit: 1g
cpus: 1.0
Parameterize Builds:
Use ARG for build-time configuration:
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine
ARG BUILD_DATE
ARG VERSION
ARG REVISION
LABEL org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.revision="${REVISION}"
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /app
COPY . .
RUN npm ci --only=${NODE_ENV}
CMD ["node", "server.js"]
Build with arguments:
docker build \
--build-arg NODE_VERSION=20 \
--build-arg VERSION=1.2.3 \
--build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--build-arg REVISION=$(git rev-parse --short HEAD) \
-t myapp:1.2.3 .
Build for Multiple Architectures:
Create images for AMD64 and ARM64:
# Create buildx builder
docker buildx create --name multiarch --use
# Build for multiple platforms
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag ghcr.io/org/app:latest \
--push .
Platform-specific optimizations:
FROM --platform=$BUILDPLATFORM node:20-alpine AS builder
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "Building on $BUILDPLATFORM for $TARGETPLATFORM"
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/main.js"]
Remove Unnecessary Files:
Clean up in the same layer:
FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
build-essential \
python3 && \
# Build your app here
apt-get purge -y build-essential && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
Analyze Image Layers:
Use dive to inspect layers:
# Install dive
brew install dive
# Analyze image
dive myapp:latest
Speed Up Multi-Stage Builds:
Use multiple FROM statements for parallel builds:
# These stages build in parallel
FROM node:20 AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20 AS tester
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm test
# Final stage depends on builder and tester
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=deps /app/node_modules ./node_modules
CMD ["node", "dist/main.js"]
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.