正在加载,请稍候…

Container Security: Docker and Kubernetes Hardening Guide

Harden Docker containers and Kubernetes clusters against attacks. Learn image scanning, Pod Security Standards, network policies, RBAC, and runtime security with Falco.

Container Security: Docker and Kubernetes Hardening

Secure Dockerfile Best Practices

# Use minimal base image
FROM node:20-alpine3.19  # Not node:latest or node:20

# Run as non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# Don't copy unnecessary files
COPY --chown=appuser:appgroup package*.json ./
RUN npm ci --only=production  # No devDependencies

COPY --chown=appuser:appgroup src/ ./src/

# Read-only filesystem where possible
RUN mkdir -p /tmp/uploads && chmod 770 /tmp/uploads

# Drop capabilities
# Handled at runtime with: --cap-drop ALL --cap-add NET_BIND_SERVICE

# Health check
HEALTHCHECK --interval=30s --timeout=3s   CMD wget -qO- http://localhost:3000/health || exit 1

# No secrets in ENV or ARG
# ENV DATABASE_URL=... <- NEVER DO THIS

EXPOSE 3000
CMD ["node", "src/server.js"]

Image Vulnerability Scanning

# Trivy - comprehensive scanner
trivy image myapp:v1.0 --severity HIGH,CRITICAL

# Fail CI if critical vulnerabilities found
trivy image myapp:v1.0 --exit-code 1 --severity CRITICAL

# Scan filesystem
trivy fs . --severity HIGH,CRITICAL

# Generate SARIF report for GitHub Actions
trivy image myapp:v1.0 --format sarif --output trivy-results.sarif

# GitHub Actions integration
# - uses: aquasecurity/trivy-action@master
#   with:
#     image-ref: 'myapp:v1.0'
#     format: 'sarif'
#     severity: 'CRITICAL,HIGH'
#     exit-code: '1'

# Grype alternative
grype myapp:v1.0 --fail-on high

Kubernetes Pod Security

# Pod Security Standard - Restricted
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted

---
# Secure Pod template
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
        seccompProfile:
          type: RuntimeDefault  # Use default seccomp profile

      containers:
        - name: myapp
          image: myapp:v1.0
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL  # Drop all capabilities
              add:
                - NET_BIND_SERVICE  # Only if binding to port < 1024
          resources:
            limits:
              cpu: "500m"
              memory: "512Mi"
            requests:
              cpu: "100m"
              memory: "128Mi"
          volumeMounts:
            - name: tmp
              mountPath: /tmp  # For writable temp dir with read-only FS

      volumes:
        - name: tmp
          emptyDir: {}

      automountServiceAccountToken: false  # Disable unless needed

RBAC Least Privilege

# Service account with minimal permissions
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: production

---
# Role - only what's needed
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: myapp-role
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list"]  # Read-only
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["myapp-secret"]  # Specific secret only
    verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: myapp-rolebinding
  namespace: production
subjects:
  - kind: ServiceAccount
    name: myapp-sa
roleRef:
  kind: Role
  name: myapp-role
  apiGroup: rbac.authorization.k8s.io

Runtime Security with Falco

# falco-rules.yaml - custom rules
- rule: Unexpected Network Connection
  desc: Detect unexpected outbound connections from containers
  condition: >
    outbound and
    container.name startswith "myapp" and
    not fd.net in (allowed_networks)
  output: >
    Unexpected connection from %container.name 
    (dest=%fd.net.sport user=%user.name cmd=%proc.cmdline)
  priority: WARNING

- rule: Shell in Container
  desc: Shell spawned in production container
  condition: >
    spawned_process and 
    container.name startswith "myapp" and
    proc.name in (shell_binaries)
  output: >
    Shell spawned in container %container.name
    (user=%user.name shell=%proc.name)
  priority: CRITICAL

- rule: Write to Sensitive File
  desc: Write to sensitive file path
  condition: >
    write_to_sensitive_file and
    container.name startswith "myapp"
  priority: HIGH

Container Security Checklist

Area Control
Image Minimal base, no root, scan vulns
Runtime Read-only FS, drop capabilities
Network Network policies, no hostNetwork
RBAC Least privilege SA, no cluster-admin
Secrets External secrets, no env vars
Monitoring Falco runtime, audit logs