Comprehensive Claude Code guidance system with: - 5 agents: tdd-guardian, code-reviewer, security-scanner, refactor-scan, dependency-audit - 18 skills covering languages (Python, TypeScript, Rust, Go, Java, C#), infrastructure (AWS, Azure, GCP, Terraform, Ansible, Docker/K8s, Database, CI/CD), testing (TDD, UI, Browser), and patterns (Monorepo, API Design, Observability) - 3 hooks: secret detection, auto-formatting, TDD git pre-commit - Strict TDD enforcement with 80%+ coverage requirements - Multi-model strategy: Opus for planning, Sonnet for execution (opusplan) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
460 lines
9.1 KiB
Markdown
460 lines
9.1 KiB
Markdown
---
|
|
name: docker-kubernetes
|
|
description: Docker containerization and Kubernetes orchestration patterns. Use when building containers, writing Dockerfiles, or deploying to Kubernetes.
|
|
---
|
|
|
|
# Docker & Kubernetes Skill
|
|
|
|
## Dockerfile Best Practices
|
|
|
|
### Multi-Stage Build (Python)
|
|
```dockerfile
|
|
# Build stage
|
|
FROM python:3.12-slim as builder
|
|
|
|
WORKDIR /app
|
|
|
|
# Install build dependencies
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install Python dependencies
|
|
COPY pyproject.toml uv.lock ./
|
|
RUN pip install uv && uv sync --frozen --no-dev
|
|
|
|
# Production stage
|
|
FROM python:3.12-slim as production
|
|
|
|
WORKDIR /app
|
|
|
|
# Create non-root user
|
|
RUN groupadd -r appuser && useradd -r -g appuser appuser
|
|
|
|
# Copy only necessary files from builder
|
|
COPY --from=builder /app/.venv /app/.venv
|
|
COPY src/ ./src/
|
|
|
|
# Set environment
|
|
ENV PATH="/app/.venv/bin:$PATH"
|
|
ENV PYTHONUNBUFFERED=1
|
|
ENV PYTHONDONTWRITEBYTECODE=1
|
|
|
|
# Switch to non-root user
|
|
USER appuser
|
|
|
|
EXPOSE 8000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
|
|
|
|
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
```
|
|
|
|
### Multi-Stage Build (Node.js)
|
|
```dockerfile
|
|
# Build stage
|
|
FROM node:22-alpine as builder
|
|
|
|
WORKDIR /app
|
|
|
|
# Install dependencies first (layer caching)
|
|
COPY package*.json ./
|
|
RUN npm ci
|
|
|
|
# Build application
|
|
COPY . .
|
|
RUN npm run build
|
|
|
|
# Production stage
|
|
FROM node:22-alpine as production
|
|
|
|
WORKDIR /app
|
|
|
|
# Create non-root user
|
|
RUN addgroup -S appuser && adduser -S appuser -G appuser
|
|
|
|
# Copy only production dependencies and built files
|
|
COPY --from=builder /app/package*.json ./
|
|
RUN npm ci --only=production && npm cache clean --force
|
|
|
|
COPY --from=builder /app/dist ./dist
|
|
|
|
USER appuser
|
|
|
|
EXPOSE 3000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
|
|
|
|
CMD ["node", "dist/main.js"]
|
|
```
|
|
|
|
### Multi-Stage Build (Rust)
|
|
```dockerfile
|
|
# Build stage
|
|
FROM rust:1.75-slim as builder
|
|
|
|
WORKDIR /app
|
|
|
|
# Create a dummy project for dependency caching
|
|
RUN cargo new --bin app
|
|
WORKDIR /app/app
|
|
|
|
# Copy manifests and build dependencies
|
|
COPY Cargo.toml Cargo.lock ./
|
|
RUN cargo build --release && rm -rf src
|
|
|
|
# Copy source and build
|
|
COPY src ./src
|
|
RUN touch src/main.rs && cargo build --release
|
|
|
|
# Production stage
|
|
FROM debian:bookworm-slim as production
|
|
|
|
# Install runtime dependencies
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
ca-certificates \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Create non-root user
|
|
RUN groupadd -r appuser && useradd -r -g appuser appuser
|
|
|
|
COPY --from=builder /app/app/target/release/app /usr/local/bin/app
|
|
|
|
USER appuser
|
|
|
|
EXPOSE 8080
|
|
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD ["/usr/local/bin/app", "health"]
|
|
|
|
CMD ["/usr/local/bin/app"]
|
|
```
|
|
|
|
## Docker Compose
|
|
|
|
### Development Setup
|
|
```yaml
|
|
# docker-compose.yml
|
|
services:
|
|
app:
|
|
build:
|
|
context: .
|
|
target: development
|
|
ports:
|
|
- "8000:8000"
|
|
volumes:
|
|
- .:/app
|
|
- /app/.venv # Exclude venv from mount
|
|
environment:
|
|
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
|
|
- REDIS_URL=redis://redis:6379/0
|
|
- DEBUG=true
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_started
|
|
|
|
db:
|
|
image: postgres:16-alpine
|
|
environment:
|
|
POSTGRES_USER: user
|
|
POSTGRES_PASSWORD: pass
|
|
POSTGRES_DB: myapp
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
volumes:
|
|
- redis_data:/data
|
|
|
|
volumes:
|
|
postgres_data:
|
|
redis_data:
|
|
```
|
|
|
|
### Production Setup
|
|
```yaml
|
|
# docker-compose.prod.yml
|
|
services:
|
|
app:
|
|
image: ${REGISTRY}/myapp:${VERSION}
|
|
deploy:
|
|
replicas: 3
|
|
resources:
|
|
limits:
|
|
cpus: '0.5'
|
|
memory: 512M
|
|
reservations:
|
|
cpus: '0.25'
|
|
memory: 256M
|
|
restart_policy:
|
|
condition: on-failure
|
|
delay: 5s
|
|
max_attempts: 3
|
|
environment:
|
|
- DATABASE_URL_FILE=/run/secrets/db_url
|
|
secrets:
|
|
- db_url
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
|
|
secrets:
|
|
db_url:
|
|
external: true
|
|
```
|
|
|
|
## Kubernetes Manifests
|
|
|
|
### Deployment
|
|
```yaml
|
|
# k8s/deployment.yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: myapp
|
|
labels:
|
|
app: myapp
|
|
spec:
|
|
replicas: 3
|
|
selector:
|
|
matchLabels:
|
|
app: myapp
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: myapp
|
|
spec:
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1000
|
|
fsGroup: 1000
|
|
containers:
|
|
- name: myapp
|
|
image: myregistry/myapp:v1.0.0
|
|
ports:
|
|
- containerPort: 8000
|
|
resources:
|
|
requests:
|
|
cpu: "100m"
|
|
memory: "128Mi"
|
|
limits:
|
|
cpu: "500m"
|
|
memory: "512Mi"
|
|
env:
|
|
- name: DATABASE_URL
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: myapp-secrets
|
|
key: database-url
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8000
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /ready
|
|
port: 8000
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 5
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
```
|
|
|
|
### Service
|
|
```yaml
|
|
# k8s/service.yaml
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: myapp
|
|
spec:
|
|
selector:
|
|
app: myapp
|
|
ports:
|
|
- port: 80
|
|
targetPort: 8000
|
|
type: ClusterIP
|
|
---
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: myapp
|
|
annotations:
|
|
kubernetes.io/ingress.class: nginx
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
spec:
|
|
tls:
|
|
- hosts:
|
|
- myapp.example.com
|
|
secretName: myapp-tls
|
|
rules:
|
|
- host: myapp.example.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: myapp
|
|
port:
|
|
number: 80
|
|
```
|
|
|
|
### ConfigMap and Secrets
|
|
```yaml
|
|
# k8s/config.yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: myapp-config
|
|
data:
|
|
LOG_LEVEL: "info"
|
|
CACHE_TTL: "3600"
|
|
---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: myapp-secrets
|
|
type: Opaque
|
|
stringData:
|
|
database-url: postgresql://user:pass@db:5432/myapp # Use sealed-secrets in production
|
|
```
|
|
|
|
### Horizontal Pod Autoscaler
|
|
```yaml
|
|
# k8s/hpa.yaml
|
|
apiVersion: autoscaling/v2
|
|
kind: HorizontalPodAutoscaler
|
|
metadata:
|
|
name: myapp
|
|
spec:
|
|
scaleTargetRef:
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
name: myapp
|
|
minReplicas: 2
|
|
maxReplicas: 10
|
|
metrics:
|
|
- type: Resource
|
|
resource:
|
|
name: cpu
|
|
target:
|
|
type: Utilization
|
|
averageUtilization: 70
|
|
- type: Resource
|
|
resource:
|
|
name: memory
|
|
target:
|
|
type: Utilization
|
|
averageUtilization: 80
|
|
```
|
|
|
|
## Helm Chart Structure
|
|
|
|
```
|
|
myapp-chart/
|
|
├── Chart.yaml
|
|
├── values.yaml
|
|
├── values-prod.yaml
|
|
├── templates/
|
|
│ ├── _helpers.tpl
|
|
│ ├── deployment.yaml
|
|
│ ├── service.yaml
|
|
│ ├── ingress.yaml
|
|
│ ├── configmap.yaml
|
|
│ ├── secret.yaml
|
|
│ └── hpa.yaml
|
|
└── charts/
|
|
```
|
|
|
|
### values.yaml
|
|
```yaml
|
|
replicaCount: 2
|
|
|
|
image:
|
|
repository: myregistry/myapp
|
|
tag: latest
|
|
pullPolicy: IfNotPresent
|
|
|
|
service:
|
|
type: ClusterIP
|
|
port: 80
|
|
|
|
ingress:
|
|
enabled: true
|
|
host: myapp.example.com
|
|
tls: true
|
|
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: 500m
|
|
memory: 512Mi
|
|
|
|
autoscaling:
|
|
enabled: true
|
|
minReplicas: 2
|
|
maxReplicas: 10
|
|
targetCPUUtilization: 70
|
|
```
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Docker
|
|
docker build -t myapp:latest .
|
|
docker build --target development -t myapp:dev .
|
|
docker run -p 8000:8000 myapp:latest
|
|
docker compose up -d
|
|
docker compose logs -f app
|
|
docker compose down -v
|
|
|
|
# Kubernetes
|
|
kubectl apply -f k8s/
|
|
kubectl get pods -l app=myapp
|
|
kubectl logs -f deployment/myapp
|
|
kubectl rollout status deployment/myapp
|
|
kubectl rollout undo deployment/myapp
|
|
kubectl port-forward svc/myapp 8000:80
|
|
|
|
# Helm
|
|
helm install myapp ./myapp-chart
|
|
helm upgrade myapp ./myapp-chart -f values-prod.yaml
|
|
helm rollback myapp 1
|
|
helm uninstall myapp
|
|
```
|
|
|
|
## Security Checklist
|
|
|
|
- [ ] Run as non-root user
|
|
- [ ] Use multi-stage builds (minimal final image)
|
|
- [ ] Pin base image versions
|
|
- [ ] Scan images for vulnerabilities (Trivy, Snyk)
|
|
- [ ] No secrets in images or environment variables
|
|
- [ ] Read-only root filesystem where possible
|
|
- [ ] Drop all capabilities, add only needed ones
|
|
- [ ] Set resource limits
|
|
- [ ] Use network policies
|
|
- [ ] Enable Pod Security Standards
|