Install
openclaw skills install cm-dockerfile-optimizerOptimize Dockerfiles for smaller images, faster builds, better security, and production readiness — multi-stage builds, layer caching, vulnerability reduction.
openclaw skills install cm-dockerfile-optimizerAnalyze and optimize Dockerfiles for smaller image sizes, faster builds, better layer caching, and production security. Reviews build stages, base images, layer ordering, secrets handling, and runtime configuration. Use when Docker images are too large, builds are slow, or preparing containers for production.
"Optimize this Dockerfile"
"Reduce my Docker image size"
"Check my Dockerfile for security issues"
"Speed up my Docker builds"
"Make this Dockerfile production-ready"
Parse the Dockerfile and analyze:
# Find all Dockerfiles
find . -name "Dockerfile*" -not -path "*/node_modules/*"
# Check current image sizes
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | head -20
# Analyze layers
docker history <image> --no-trunc --format "{{.Size}}\t{{.CreatedBy}}" 2>/dev/null
Base image optimization:
node:18 (900MB) → node:18-slim (200MB) → node:18-alpine (120MB)python:3.12 (1GB) → python:3.12-slim (140MB) → python:3.12-alpine (50MB)ubuntu:22.04 (77MB) → debian:bookworm-slim (74MB) → alpine:3.19 (7MB)gcr.io/distroless/nodejs20 (130MB):latest is unpredictable)Layer optimization:
apt-get clean && rm -rf /var/lib/apt/lists/*.dockerignore to exclude node_modules, .git, tests, docsMulti-stage builds:
--mount=type=cache,target=/root/.npmContent analysis:
Layer caching:
COPY package.json package-lock.json ./ before COPY . .BuildKit features:
--mount=type=cache for persistent package caches--mount=type=secret for build-time secrets--mount=type=ssh for private repo accessCI integration:
--cache-from / --cache-toUSER 1001)COPY --chown instead of RUN chownHEALTHCHECK instruction presentEXPOSE documents the correct portsENTRYPOINT vs CMD used correctlytini or --init)## Dockerfile Optimization Report
**Current image:** myapp:latest (847MB, 23 layers)
**Optimized estimate:** ~95MB (8 layers)
### 🔴 Critical Issues (3)
1. **Running as root** — no USER instruction
→ Add: `RUN addgroup -g 1001 app && adduser -u 1001 -G app -D app`
→ Add: `USER app` before ENTRYPOINT
2. **Secret in build arg** — `ARG DB_PASSWORD`
→ Use `--mount=type=secret` or runtime env var
3. **No .dockerignore** — sending 2.1GB build context
→ Create .dockerignore: node_modules, .git, *.md, tests/
### ⚡ Size Reduction
| Change | Size Impact |
|--------|------------|
| node:18 → node:18-alpine | -780MB |
| Multi-stage build | -340MB (dev deps) |
| .dockerignore | -2.1GB context |
| Combined RUN layers | -45MB (cache) |
| **Total** | **847MB → ~95MB (-89%)** |
### 🏗️ Optimized Dockerfile
```dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
RUN addgroup -g 1001 app && adduser -u 1001 -G app -D app
WORKDIR /app
COPY --from=builder --chown=app:app /app/dist ./dist
COPY --from=builder --chown=app:app /app/node_modules ./node_modules
COPY --from=builder --chown=app:app /app/package.json ./
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s CMD wget -qO- http://localhost:3000/health
ENTRYPOINT ["node", "dist/index.js"]