Claude-skill-registry docker-reviewer
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/docker-reviewer" ~/.claude/skills/majiayu000-claude-skill-registry-docker-reviewer && rm -rf "$T"
manifest:
skills/data/docker-reviewer/SKILL.mdsource content
Docker Reviewer Skill
Purpose
Reviews Dockerfiles and docker-compose configurations for optimization, security, and best practices.
When to Use
- Dockerfile code review
- Docker image optimization
- docker-compose.yml review
- Container security audit
- Build time optimization
Project Detection
in projectDockerfile
ordocker-compose.ymldocker-compose.yaml
file.dockerignore
variantsDockerfile.*
Workflow
Step 1: Analyze Project
**Base Image**: node:20-alpine **Build Type**: Multi-stage **Compose**: v3.8 **Registry**: Docker Hub / ECR / GCR
Step 2: Select Review Areas
AskUserQuestion:
"Which areas to review?" Options: - Full Docker review (recommended) - Dockerfile optimization - Layer caching strategy - Security hardening - docker-compose review multiSelect: true
Detection Rules
Image Optimization
| Check | Recommendation | Severity |
|---|---|---|
| Large base image | Use alpine/slim/distroless | HIGH |
| No multi-stage build | Add build stage | MEDIUM |
| Too many layers | Combine RUN commands | MEDIUM |
| Installing dev deps | Separate build/runtime | HIGH |
# BAD: Large image with dev dependencies FROM node:20 WORKDIR /app COPY . . RUN npm install RUN npm run build CMD ["node", "dist/index.js"] # Result: ~1GB image # GOOD: Multi-stage with alpine FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules USER node CMD ["node", "dist/index.js"] # Result: ~150MB image
Layer Caching
| Check | Recommendation | Severity |
|---|---|---|
| COPY . before install | Copy package files first | HIGH |
| No .dockerignore | Add .dockerignore | MEDIUM |
| Changing files early | Order by change frequency | MEDIUM |
# BAD: Cache invalidation on every code change FROM node:20-alpine WORKDIR /app COPY . . # Invalidates cache on ANY change RUN npm install # Always reinstalls # GOOD: Leverage layer caching FROM node:20-alpine WORKDIR /app COPY package*.json ./ # Only invalidates on package change RUN npm ci # Cached if packages unchanged COPY . . # Code changes don't affect npm cache RUN npm run build
# .dockerignore node_modules .git .gitignore *.md .env* dist coverage .nyc_output
Security
| Check | Recommendation | Severity |
|---|---|---|
| Running as root | Add USER directive | CRITICAL |
| Latest tag | Pin specific version | HIGH |
| Secrets in build | Use build secrets | CRITICAL |
| No health check | Add HEALTHCHECK | MEDIUM |
# BAD: Security issues FROM node:latest # Unpinned version WORKDIR /app COPY . . ENV API_KEY=secret123 # Secret in image! RUN npm install CMD ["node", "index.js"] # Running as root # GOOD: Secure Dockerfile FROM node:20.10-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production FROM node:20.10-alpine WORKDIR /app # Create non-root user RUN addgroup -g 1001 appgroup && \ adduser -u 1001 -G appgroup -s /bin/sh -D appuser COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules COPY --chown=appuser:appgroup . . USER appuser HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1 EXPOSE 3000 CMD ["node", "index.js"]
Build Secrets (Docker BuildKit)
# syntax=docker/dockerfile:1.4 FROM node:20-alpine WORKDIR /app # Mount secret during build (not stored in layer) RUN --mount=type=secret,id=npm_token \ NPM_TOKEN=$(cat /run/secrets/npm_token) \ npm ci # Build command: # DOCKER_BUILDKIT=1 docker build --secret id=npm_token,src=.npmrc .
RUN Optimization
| Check | Recommendation | Severity |
|---|---|---|
| Multiple RUN for cleanup | Combine in single RUN | MEDIUM |
| No cleanup after install | Remove cache in same layer | MEDIUM |
# BAD: Multiple layers, cache not cleaned RUN apt-get update RUN apt-get install -y curl RUN apt-get clean # GOOD: Single layer with cleanup RUN apt-get update && \ apt-get install -y --no-install-recommends curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*
Docker Compose
| Check | Recommendation | Severity |
|---|---|---|
| No resource limits | Add deploy.resources | HIGH |
| No health checks | Add healthcheck | MEDIUM |
| Hardcoded config | Use environment variables | MEDIUM |
| No restart policy | Add restart: unless-stopped | MEDIUM |
# BAD: Minimal compose version: '3.8' services: app: build: . ports: - "3000:3000" db: image: postgres environment: POSTGRES_PASSWORD: password123 # GOOD: Production-ready compose version: '3.8' services: app: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=postgresql://user:${DB_PASSWORD}@db:5432/app depends_on: db: condition: service_healthy restart: unless-stopped deploy: resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s db: image: postgres:15-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: app volumes: - postgres_data:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d app"] interval: 10s timeout: 5s retries: 5 volumes: postgres_data:
Response Template
## Docker Review Results **Project**: [name] **Base Image**: node:20-alpine **Build**: Multi-stage | **Compose**: v3.8 ### Image Optimization | Status | File | Issue | |--------|------|-------| | HIGH | Dockerfile | Using node:latest (~1GB) | ### Layer Caching | Status | File | Issue | |--------|------|-------| | HIGH | Dockerfile:5 | COPY . before npm install | ### Security | Status | File | Issue | |--------|------|-------| | CRITICAL | Dockerfile | Running as root user | ### Compose | Status | File | Issue | |--------|------|-------| | HIGH | docker-compose.yml | No resource limits | ### Recommended Actions 1. [ ] Switch to node:20-alpine base image 2. [ ] Add multi-stage build 3. [ ] Add USER directive for non-root 4. [ ] Add resource limits in compose
Best Practices
- Base Image: Use alpine/slim/distroless
- Multi-stage: Separate build and runtime
- Caching: Order by change frequency
- Security: Non-root, pinned versions, no secrets
- Compose: Health checks, resource limits
Integration
: Kubernetes deploymentsk8s-reviewer
: Container securitysecurity-scanner
: Build pipelinesci-cd-reviewer