DEV Community

Andrew
Andrew

Posted on

Container Security: Hardening Your Docker & Kubernetes

Container Security Best Practices πŸ”

Image Security

Scan for Vulnerabilities

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image myapp:latest

# Critical vulnerabilities found
Enter fullscreen mode Exit fullscreen mode

Use Distroless Images

FROM python:3.11 AS builder
COPY requirements.txt .
RUN pip install -r requirements.txt

FROM gcr.io/distroless/python3-nonroot
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY app.py /app.py
ENTRYPOINT ["python", "/app.py"]
Enter fullscreen mode Exit fullscreen mode

Sign Images

cosign sign --key cosign.key myapp:latest
cosign verify --key cosign.pub myapp:latest
Enter fullscreen mode Exit fullscreen mode

Kubernetes Pod Security

SecurityContext

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
  - name: app
    image: myapp:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}
Enter fullscreen mode Exit fullscreen mode

Pod Security Standards

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'
  runAsUser:
    rule: 'MustRunAsNonRoot'
Enter fullscreen mode Exit fullscreen mode

Network Security

Network Policies

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: app-netpol
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            name: production
      ports:
      - protocol: TCP
        port: 8080
  egress:
    - to:
      - namespaceSelector:
          matchLabels:
            name: production
      ports:
      - protocol: TCP
        port: 5432
Enter fullscreen mode Exit fullscreen mode

Runtime Security

AppArmor/SELinux

# Check AppArmor status
aa-status

# Load profile
apparmor_parser /etc/apparmor.d/docker-profile
Enter fullscreen mode Exit fullscreen mode

Resource Limits

resources:
  requests:
    memory: "64Mi"
    cpu: "250m"
  limits:
    memory: "128Mi"
    cpu: "500m"
Enter fullscreen mode Exit fullscreen mode

Supply Chain Security

  • βœ… Signed images
  • βœ… Verified base images
  • βœ… SBOMs (Software Bill of Materials)
  • βœ… Attestations
  • βœ… Image provenance

Security Checklist

  • βœ… No root container
  • βœ… Image scanned for vulnerabilities
  • βœ… Secrets not in image
  • βœ… Read-only filesystem
  • βœ… Capabilities dropped
  • βœ… Network policies enforced
  • βœ… Resource limits set
  • βœ… Pod security policies in place

Top comments (0)