From harness-claude
Reviews Dockerfiles for layer efficiency, security, and size optimization; validates Kubernetes manifests, Helm charts, and docker-compose files for best practices.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Dockerfile review, Kubernetes manifest validation, and container optimization. Smaller images, safer containers, correct orchestration.
Optimizes Docker containers for performance and security with multi-stage builds, orchestration patterns via Compose/Swarm, and production deployment strategies. Analyzes Dockerfiles, environments, and validates builds.
Builds production-ready Docker images with multi-stage builds, non-root users, .dockerignore security, and pinned base images. Reviews, diagnoses, and debugs Dockerfiles and container issues.
Checks and configures container infrastructure including Dockerfiles, build workflows, registries, scanning, and devcontainers for minimal images, non-root users, and security hardening.
Share bugs, ideas, or general feedback.
Dockerfile review, Kubernetes manifest validation, and container optimization. Smaller images, safer containers, correct orchestration.
Locate container files. Search the project for container-related configuration:
Dockerfile, Dockerfile.* (multi-target builds)docker-compose.yml, docker-compose.*.yml (override files).dockerignorek8s/, kubernetes/, manifests/ directorieshelm/, charts/ directoriesskaffold.yaml, tilt.json (dev tooling)Identify base images. Parse each Dockerfile for FROM directives:
latest tagInventory Kubernetes resources. Parse manifest files and record:
Detect Helm usage. If Helm charts exist:
Chart.yaml for version and dependenciesvalues.yaml for configurable parametersPresent scan summary:
Container Scan:
Dockerfiles: 2 (app, worker)
Compose files: 1 (docker-compose.yml + docker-compose.dev.yml)
K8s manifests: 8 resources across 2 namespaces
Helm charts: 1 (app chart with 3 subcharts)
Base images: node:20-alpine, python:3.12-slim
Analyze Dockerfile layer efficiency. Check each Dockerfile for:
.dockerignore completenessCheck container security posture. Evaluate:
Evaluate Kubernetes resource definitions. For each Deployment/StatefulSet:
Analyze docker-compose configuration. Check for:
Check image tag strategy. Verify:
latest tag in production manifestsRecommend image size reduction. For each Dockerfile:
.dockerignore to exclude test files, docs, and dev configsRecommend build performance improvements.
Reorder COPY directives to maximize layer cache hits
Use BuildKit features (cache mounts for package managers)
Split slow-changing layers (OS packages) from fast-changing layers (app code)
Example for Node.js:
# Good: dependency layer cached separately
COPY package.json package-lock.json ./
RUN npm ci --production
COPY src/ ./src/
Recommend Kubernetes improvements.
Recommend security hardening.
Generate optimization summary with estimated impact:
Optimization Summary:
Image size: 850MB -> ~180MB (switch to alpine + multi-stage)
Build time: ~4m -> ~2m (layer reordering + cache mounts)
Security: 3 findings (non-root, capabilities, image pinning)
K8s: 5 resources missing resource limits
Validate Dockerfile syntax. Run docker build --check or parse for common errors:
Validate Kubernetes manifests. Check for:
Validate Helm charts. If Helm is used:
helm lint passesValidate docker-compose. Check for:
Generate validation report:
Container Validation: [PASS/WARN/FAIL]
Dockerfiles: PASS (2/2 valid)
K8s manifests: WARN (label mismatch in worker-service.yaml)
Helm chart: PASS (lint clean)
Compose: PASS (valid structure)
Issues:
1. k8s/worker-service.yaml: selector "app: worker" does not match
deployment label "app: worker-v2" -- requests will not route
harness skill run harness-containerization -- Primary invocation for container review.harness validate -- Run after configuration changes to verify project health.harness check-deps -- Verify container tooling dependencies are available.emit_interaction -- Present optimization recommendations and gather decisions.latest in production)Phase 1: SCAN
Found: Dockerfile (app), Dockerfile.worker, docker-compose.dev.yml
K8s: 12 manifests in k8s/ (2 Deployments, 2 Services, 2 ConfigMaps,
2 HPA, 2 Ingress, 2 PDB)
Base images: node:20 (not alpine), node:20 (worker)
Phase 2: ANALYZE
Dockerfile issues:
- node:20 full image (940MB) -- use node:20-alpine (180MB)
- No .dockerignore -- node_modules and .git copied into image
- No USER directive -- running as root
- No HEALTHCHECK
K8s issues:
- worker deployment missing memory limits
- No network policies defined
- Liveness probe on /healthz but no readiness probe
Phase 3: OPTIMIZE
1. Switch to node:20-alpine -- saves ~760MB per image
2. Add .dockerignore with node_modules, .git, tests, docs
3. Add multi-stage build: builder stage for npm ci, runtime for app
4. Add USER node (UID 1000) after COPY
5. Add readiness probe on /ready endpoint
6. Add memory limit of 512Mi to worker deployment
Phase 4: VALIDATE
Dockerfiles: WARN (2 security findings, 1 size finding)
K8s manifests: WARN (missing limits, missing readiness probe)
Compose: PASS
Result: WARN -- 6 actionable improvements identified
Phase 1: SCAN
Found: Dockerfile (multi-stage with distroless runtime)
Helm chart: charts/api/ with values.yaml
Base images: python:3.12-slim (builder), gcr.io/distroless/python3 (runtime)
Phase 2: ANALYZE
Dockerfile: Well-structured multi-stage build
- Builder installs dependencies, runtime copies only venv
- Distroless base (no shell, minimal attack surface)
- Non-root user configured
Helm:
- Resource limits set in values.yaml
- Probes configured with appropriate timeouts
- HPA configured for 2-10 replicas
Phase 3: OPTIMIZE
Minor recommendations only:
- Pin distroless image to digest for reproducibility
- Add --mount=type=cache for pip downloads in builder stage
- Add pod anti-affinity to spread replicas across nodes
Phase 4: VALIDATE
Dockerfile: PASS
Helm lint: PASS
Template render: PASS (all values resolve)
Result: PASS -- well-configured container setup
| Rationalization | Reality |
|---|---|
"We use latest in production because we always want the most recent image" | latest is a mutable pointer. A deployment at 9am and a rollback at 9pm may pull different image contents with the same tag. Immutable tags (semver or digest) are required for reproducible deployments and reliable rollbacks. |
| "The container runs as root because it needs to bind to port 80" | Binding to a privileged port requires elevated capability, not full root access. The correct solution is to run the container as a non-root user and use --cap-add NET_BIND_SERVICE, or to expose a high port and use a load balancer or ingress for port translation. |
| "We don't set resource limits because we want the container to use whatever it needs" | Containers without memory limits can exhaust node memory, triggering OOM kills of other containers on the same node. Kubernetes uses resource requests for scheduling and limits for safety; omitting limits transfers the risk of one container onto the entire node. |
| "Our image is 2GB but it only takes a few seconds to pull in our CI" | Image size multiplies across every developer pull, every CI run, and every Kubernetes pod startup. A 2GB image that takes 3 seconds to pull in CI with a warm cache takes 90 seconds on a cold node during an autoscaling event at peak traffic. |
| "We don't need liveness and readiness probes — the container exits if it crashes" | Process exit is a coarse health signal. A process that is running but deadlocked, stuck in an infinite retry loop, or unable to connect to its database will never exit. Kubernetes will continue routing traffic to it. Readiness probes prevent traffic routing to unhealthy containers that are still running. |
latest tag in production manifests. Production Kubernetes manifests or compose files using latest image tags are blocking findings. Immutable tags or digests are required.--changed-only flag) and scheduling a full audit separately.