Use this skill when containerizing applications, writing Dockerfiles, deploying to Kubernetes, creating Helm charts, or configuring service mesh. Triggers on Docker, Kubernetes, k8s, containers, pods, deployments, services, ingress, Helm, Istio, container orchestration, and any task requiring container or cluster management.
When this skill is activated, always start your first response with the 🧢 emoji.
A practical guide to containerizing applications and running them reliably in Kubernetes. This skill covers the full lifecycle from writing a production-ready Dockerfile to deploying with Helm, configuring traffic with Ingress, and debugging cluster issues. The emphasis is on correctness and operability - containers that are small, secure, and observable; Kubernetes workloads that self-heal, scale, and fail gracefully. Designed for engineers who know the basics and need opinionated guidance on production patterns.
Trigger this skill when the user:
Do NOT trigger this skill for:
One process per container - A container should do exactly one thing. Sidecar patterns (logging agents, proxies) are valid, but the main container must not run multiple application processes. This preserves independent restartability and clean signal handling.
Immutable infrastructure - Never patch a running container. Update the image
tag, redeploy. Mutations to running pods are invisible to version control and
create snowflakes. Pin image tags in production; never use latest.
Declarative configuration - All cluster state lives in YAML checked into git.
kubectl apply is the only allowed mutation path. kubectl edit on a live cluster
is a debugging tool, not a deployment method.
Minimal base images - Use alpine, distroless, or language-specific slim
images. Fewer packages = smaller attack surface = faster pulls. Multi-stage builds
eliminate build tooling from the final image.
Health checks always - Every Deployment must define liveness and readiness probes. Without them, Kubernetes cannot distinguish a booting pod from a hung one, and will route traffic to pods that cannot serve it.
Each RUN, COPY, and ADD instruction creates a layer. Layers are cached by
content hash. Cache is invalidated at the first changed layer and all layers after
it. Ordering matters: put rarely-changing instructions (installing OS packages) before
frequently-changing ones (copying application source). Copy dependency manifests and
install before copying source code.
Pod -> smallest schedulable unit (one or more containers sharing network/storage)
|
Deployment -> manages ReplicaSets; handles rollouts and rollbacks
|
Service -> stable virtual IP and DNS name that routes to healthy pod IPs
|
Ingress -> HTTP/HTTPS routing rules from outside the cluster into Services
Namespaces provide soft isolation within a cluster. Use them to separate environments (staging, production) or teams. ResourceQuotas and NetworkPolicies scope to namespaces.
# ---- build stage ----
FROM node:20-alpine AS builder
WORKDIR /app
# Copy manifests first - cached until dependencies change
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY . .
RUN npm run build
# ---- runtime stage ----
FROM node:20-alpine AS runtime
ENV NODE_ENV=production
WORKDIR /app
# Non-root user for security
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
USER appuser
EXPOSE 3000
# Use exec form to receive signals correctly
CMD ["node", "dist/server.js"]
Key decisions: alpine base, non-root user, npm ci (reproducible installs),
multi-stage to exclude dev dependencies, exec-form CMD for proper PID 1 signal
handling.
apiVersion: apps/v1