Overview
Container security encompasses protecting containerized applications throughout their lifecycle, from image creation to runtime operations. This includes securing container images, runtime environments, orchestration platforms, and the underlying infrastructure.
Container Security Fundamentals
Security Principles
Core security concepts for containers:
Defense in Depth
- Image security scanning
- Runtime protection
- Network segmentation
- Access controls
- Monitoring and logging
Least Privilege
- Minimal base images
- Non-root user execution
- Limited capabilities
- Resource constraints
- Network policies
Zero Trust Architecture
- Verify every request
- Encrypt communications
- Monitor continuously
- Assume breach scenarios
Docker Security
Secure Dockerfile Practices
Best practices for secure container images:
# Use official, minimal base images
FROM alpine:3.18 AS builder
# Avoid 'latest' tag in production
# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
# Update packages and install only necessary components
RUN apk update && apk upgrade && \
apk add --no-cache \
ca-certificates \
curl && \
rm -rf /var/cache/apk/*
# Set secure working directory
WORKDIR /app
# Copy application with proper ownership
COPY --chown=appuser:appgroup ./app /app/
# Remove unnecessary packages after build
RUN apk del curl
# Multi-stage build for smaller final image
FROM alpine:3.18
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
COPY --from=builder --chown=appuser:appgroup /app /app
# Switch to non-root user
USER appuser
# Expose only necessary ports
EXPOSE 8080
# Use specific entrypoint
ENTRYPOINT ["/app/myapp"]
# Add health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
Container Image Scanning
Implement automated vulnerability scanning:
#!/bin/bash
# container-scan.sh - Image security scanning script
IMAGE_NAME="$1"
SEVERITY_THRESHOLD="HIGH"
SCAN_RESULTS_DIR="./scan-results"
# Create results directory
mkdir -p "$SCAN_RESULTS_DIR"
# Trivy security scan
echo "Running Trivy security scan..."
trivy image --severity "$SEVERITY_THRESHOLD" --format json \
--output "$SCAN_RESULTS_DIR/trivy-$(date +%Y%m%d-%H%M%S).json" \
"$IMAGE_NAME"
# Docker Scout scan (if available)
if command -v docker &> /dev/null; then
echo "Running Docker Scout scan..."
docker scout cves --format json \
--output "$SCAN_RESULTS_DIR/scout-$(date +%Y%m%d-%H%M%S).json" \
"$IMAGE_NAME"
fi
# Snyk scan (if available)
if command -v snyk &> /dev/null; then
echo "Running Snyk container scan..."
snyk container test "$IMAGE_NAME" \
--json > "$SCAN_RESULTS_DIR/snyk-$(date +%Y%m%d-%H%M%S).json"
fi
# Check scan results
CRITICAL_VULNS=$(trivy image --severity CRITICAL --format json "$IMAGE_NAME" | jq '.Results[]?.Vulnerabilities // [] | length')
if [ "$CRITICAL_VULNS" -gt 0 ]; then
echo "CRITICAL: Found $CRITICAL_VULNS critical vulnerabilities"
exit 1
else
echo "SUCCESS: No critical vulnerabilities found"
exit 0
fi
Docker Daemon Security
Secure Docker daemon configuration:
// /etc/docker/daemon.json
{
"icc": false,
"userns-remap": "default",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true,
"userland-proxy": false,
"experimental": false,
"selinux-enabled": true,
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"default-ulimits": {
"nofile": {
"name": "nofile",
"hard": 65536,
"soft": 65536
}
},
"tls": true,
"tlsverify": true,
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"tlscacert": "/etc/docker/certs/ca.pem",
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}
Runtime Security Controls
Implement runtime security measures:
#!/bin/bash
# secure-container-run.sh - Secure container runtime script
IMAGE="$1"
CONTAINER_NAME="$2"
# Run container with security hardening
docker run -d \
--name "$CONTAINER_NAME" \
--user 1001:1001 \
--read-only \
--tmpfs /tmp:noexec,nosuid,size=100m \
--tmpfs /var/run:noexec,nosuid,size=50m \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
--security-opt seccomp=seccomp-profile.json \
--security-opt apparmor=docker-default \
--memory 256m \
--memory-swap 256m \
--cpu-shares 512 \
--pids-limit 100 \
--ulimit nofile=1024:1024 \
--network custom-network \
--restart unless-stopped \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
"$IMAGE"
# Verify container security settings
echo "Container security verification:"
docker inspect "$CONTAINER_NAME" | jq '.[] | {
User: .Config.User,
ReadonlyRootfs: .HostConfig.ReadonlyRootfs,
CapDrop: .HostConfig.CapDrop,
CapAdd: .HostConfig.CapAdd,
SecurityOpt: .HostConfig.SecurityOpt,
Memory: .HostConfig.Memory,
PidsLimit: .HostConfig.PidsLimit
}'
Kubernetes Security
Pod Security Standards
Implement Pod Security Standards (PSS):
# pod-security-policy.yaml
apiVersion: v1
kind: Namespace
metadata:
name: secure-namespace
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
# Secure pod example
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
namespace: secure-namespace
spec:
serviceAccountName: restricted-sa
securityContext:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1001
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
volumeMounts:
- name: tmp
mountPath: /tmp
- name: var-run
mountPath: /var/run
volumes:
- name: tmp
emptyDir:
sizeLimit: 100Mi
- name: var-run
emptyDir:
sizeLimit: 50Mi
Network Policies
Implement network segmentation:
# network-security-policies.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
# Allow specific ingress traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# Deny all egress except DNS and specific services
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-egress
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
# Allow DNS
- to: []
ports:
- protocol: UDP
port: 53
# Allow HTTPS to external APIs
- to: []
ports:
- protocol: TCP
port: 443
# Allow internal service communication
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
RBAC Configuration
Implement Role-Based Access Control:
# rbac-security.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-service-account
namespace: production
---
# Minimal role for application
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: app-role
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["app-secrets"]
---
# Bind role to service account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-role-binding
namespace: production
subjects:
- kind: ServiceAccount
name: app-service-account
namespace: production
roleRef:
kind: Role
name: app-role
apiGroup: rbac.authorization.k8s.io
---
# ClusterRole for monitoring (read-only)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-reader
rules:
- apiGroups: [""]
resources: ["nodes", "pods", "services", "endpoints"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
resources: ["*"]
verbs: ["get", "list"]
Secret Management
Kubernetes Secrets Security
Secure secret handling practices:
# secure-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
namespace: production
annotations:
kubernetes.io/description: "Application secrets"
type: Opaque
data:
database-password: <base64-encoded-password>
api-key: <base64-encoded-api-key>
---
# Secret consumption in pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
namespace: production
spec:
replicas: 2
selector:
matchLabels:
app: secure-app
template:
metadata:
labels:
app: secure-app
spec:
serviceAccountName: app-service-account
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 1001
containers:
- name: app
image: myapp:v1.0
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: database-password
- name: API_KEY
valueFrom:
secretKeyRef:
name: app-secrets
key: api-key
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: app-secrets
defaultMode: 0400
External Secret Management
Integration with external secret stores:
# external-secrets.yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
namespace: production
spec:
provider:
vault:
server: "https://vault.company.com"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "production-role"
serviceAccountRef:
name: "external-secrets-sa"
---
# External secret definition
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-external-secret
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: app-secrets
creationPolicy: Owner
data:
- secretKey: database-password
remoteRef:
key: production/database
property: password
- secretKey: api-key
remoteRef:
key: production/api
property: key
Image Security
Image Signing and Verification
Implement image signing with Cosign:
#!/bin/bash
# image-signing.sh - Image signing and verification
IMAGE="myapp:v1.0"
REGISTRY="registry.company.com"
FULL_IMAGE="$REGISTRY/$IMAGE"
# Generate key pair (one-time setup)
cosign generate-key-pair
# Sign the image
cosign sign --key cosign.key "$FULL_IMAGE"
# Verify signature
cosign verify --key cosign.pub "$FULL_IMAGE"
# Sign with keyless signing (OIDC)
cosign sign "$FULL_IMAGE"
# Create attestation
cosign attest --predicate attestation.json --key cosign.key "$FULL_IMAGE"
# Verify attestation
cosign verify-attestation --key cosign.pub "$FULL_IMAGE"
Supply Chain Security
SLSA (Supply-chain Levels for Software Artifacts) implementation:
# slsa-build-workflow.yml
name: SLSA Build and Sign
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: ubuntu-latest
outputs:
image: ${{ steps.build.outputs.image }}
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v4
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.company.com
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: registry.company.com/myapp:${{ github.sha }}
platforms: linux/amd64,linux/arm64
provenance: true
sbom: true
- name: Generate SLSA provenance
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
with:
image: registry.company.com/myapp
digest: ${{ steps.build.outputs.digest }}
registry-username: ${{ secrets.REGISTRY_USERNAME }}
registry-password: ${{ secrets.REGISTRY_PASSWORD }}
Runtime Security
Runtime Protection
Implement runtime security monitoring:
# falco-security-rules.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: falco-rules
namespace: falco-system
data:
custom_rules.yaml: |
# Custom security rules
- rule: Unexpected Network Traffic
desc: Detect unexpected network connections
condition: >
outbound and
not proc.name in (curl, wget, http) and
not fd.net.sport in (80, 443, 53)
output: >
Unexpected network traffic (user=%user.name proc=%proc.name
connection=%fd.name)
priority: WARNING
- rule: Sensitive File Access
desc: Detect access to sensitive files
condition: >
open_read and
fd.name in (/etc/passwd, /etc/shadow, /etc/ssh/sshd_config) and
not proc.name in (sshd, systemd)
output: >
Sensitive file accessed (user=%user.name proc=%proc.name
file=%fd.name)
priority: CRITICAL
- rule: Container Privilege Escalation
desc: Detect privilege escalation attempts
condition: >
spawned_process and
proc.name in (sudo, su, pkexec) and
container
output: >
Privilege escalation in container (user=%user.name
proc=%proc.name container=%container.name)
priority: CRITICAL
---
# Falco deployment
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: falco
namespace: falco-system
spec:
selector:
matchLabels:
app: falco
template:
metadata:
labels:
app: falco
spec:
serviceAccount: falco
hostNetwork: true
hostPID: true
containers:
- name: falco
image: falcosecurity/falco:0.36.1
securityContext:
privileged: true
args:
- /usr/bin/falco
- --cri=/run/containerd/containerd.sock
- --k8s-api=https://kubernetes.default.svc.cluster.local
- --k8s-api-cert=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
- --k8s-api-token=/var/run/secrets/kubernetes.io/serviceaccount/token
volumeMounts:
- name: dev-fs
mountPath: /host/dev
- name: proc-fs
mountPath: /host/proc
- name: etc-fs
mountPath: /host/etc
- name: falco-rules
mountPath: /etc/falco/rules.d
volumes:
- name: dev-fs
hostPath:
path: /dev
- name: proc-fs
hostPath:
path: /proc
- name: etc-fs
hostPath:
path: /etc
- name: falco-rules
configMap:
name: falco-rules
Container Isolation
Advanced isolation techniques:
# gvisor-runtime-class.yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: gvisor
handler: runsc
---
# Pod using gVisor runtime
apiVersion: v1
kind: Pod
metadata:
name: secure-isolated-pod
spec:
runtimeClassName: gvisor
securityContext:
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
limits:
memory: "128Mi"
cpu: "100m"
requests:
memory: "64Mi"
cpu: "50m"
Compliance and Governance
Security Policies
Policy as Code with Open Policy Agent (OPA):
# security-policies.rego
package kubernetes.security
# Deny containers running as root
deny[msg] {
input.kind == "Pod"
input.spec.securityContext.runAsUser == 0
msg := "Container must not run as root user"
}
# Require security context
deny[msg] {
input.kind == "Pod"
not input.spec.securityContext
msg := "Pod must have security context defined"
}
# Require resource limits
deny[msg] {
input.kind == "Pod"
container := input.spec.containers[_]
not container.resources.limits
msg := sprintf("Container %s must have resource limits", [container.name])
}
# Deny privileged containers
deny[msg] {
input.kind == "Pod"
container := input.spec.containers[_]
container.securityContext.privileged == true
msg := sprintf("Privileged container %s is not allowed", [container.name])
}
# Require specific image registries
deny[msg] {
input.kind == "Pod"
container := input.spec.containers[_]
not startswith(container.image, "registry.company.com/")
msg := sprintf("Container %s must use approved registry", [container.name])
}
# Deny host network access
deny[msg] {
input.kind == "Pod"
input.spec.hostNetwork == true
msg := "Host network access is not allowed"
}
Admission Controllers
Custom admission controller for security enforcement:
# admission-controller.yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionWebhook
metadata:
name: security-validator
webhooks:
- name: security.company.com
clientConfig:
service:
name: security-admission-controller
namespace: security-system
path: "/validate"
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
- operations: ["CREATE", "UPDATE"]
apiGroups: ["apps"]
apiVersions: ["v1"]
resources: ["deployments", "replicasets"]
failurePolicy: Fail
admissionReviewVersions: ["v1", "v1beta1"]
---
# Mutating webhook for security defaults
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionWebhook
metadata:
name: security-mutator
webhooks:
- name: security-defaults.company.com
clientConfig:
service:
name: security-admission-controller
namespace: security-system
path: "/mutate"
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
failurePolicy: Fail
admissionReviewVersions: ["v1", "v1beta1"]
Monitoring and Incident Response
Security Monitoring
Comprehensive security monitoring setup:
# security-monitoring.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: security-monitoring-config
namespace: monitoring
data:
prometheus-rules.yaml: |
groups:
- name: container-security
rules:
- alert: ContainerHighPrivileged
expr: kube_pod_container_status_running{container!="POD"} * on(pod, namespace) kube_pod_spec_containers_security_context_privileged == 1
for: 0m
labels:
severity: critical
annotations:
summary: "Privileged container detected"
description: "Container {{ $labels.container }} in pod {{ $labels.pod }} is running in privileged mode"
- alert: ContainerRootUser
expr: kube_pod_container_status_running{container!="POD"} * on(pod, namespace) kube_pod_spec_containers_security_context_run_as_user == 0
for: 0m
labels:
severity: warning
annotations:
summary: "Container running as root"
description: "Container {{ $labels.container }} in pod {{ $labels.pod }} is running as root user"
- alert: UnauthorizedImagePull
expr: increase(kubernetes_build_info[5m]) and on(instance) kube_pod_container_info{image!~"registry.company.com/.*"}
for: 0m
labels:
severity: critical
annotations:
summary: "Unauthorized container image"
description: "Pod {{ $labels.pod }} is using unauthorized image {{ $labels.image }}"
---
# Security incident response workflow
apiVersion: v1
kind: ConfigMap
metadata:
name: incident-response-playbook
namespace: security
data:
playbook.yaml: |
incident_types:
privileged_container:
severity: high
actions:
- isolate_pod
- collect_logs
- notify_security_team
- create_incident_ticket
unauthorized_image:
severity: critical
actions:
- block_image
- quarantine_pod
- scan_for_malware
- escalate_to_management
suspicious_network_activity:
severity: medium
actions:
- capture_network_traffic
- analyze_connections
- update_network_policies
Automated Response
Automated incident response system:
#!/usr/bin/env python3
# security-response-handler.py
import json
import subprocess
import logging
from kubernetes import client, config
from datetime import datetime
class SecurityIncidentHandler:
def __init__(self):
config.load_incluster_config()
self.k8s_client = client.CoreV1Api()
self.apps_client = client.AppsV1Api()
def handle_privileged_container_alert(self, alert_data):
"""Handle privileged container detection"""
namespace = alert_data.get('namespace')
pod_name = alert_data.get('pod')
logging.warning(f"Privileged container detected: {namespace}/{pod_name}")
# Isolate the pod
self.isolate_pod(namespace, pod_name)
# Collect forensic data
self.collect_pod_logs(namespace, pod_name)
# Create security incident
self.create_incident("PRIVILEGED_CONTAINER", alert_data)
def isolate_pod(self, namespace, pod_name):
"""Apply network isolation to suspicious pod"""
isolation_policy = {
"apiVersion": "networking.k8s.io/v1",
"kind": "NetworkPolicy",
"metadata": {
"name": f"isolate-{pod_name}",
"namespace": namespace
},
"spec": {
"podSelector": {
"matchLabels": {"security.company.com/isolated": "true"}
},
"policyTypes": ["Ingress", "Egress"]
}
}
# Label the pod for isolation
try:
body = {"metadata": {"labels": {"security.company.com/isolated": "true"}}}
self.k8s_client.patch_namespaced_pod(
name=pod_name,
namespace=namespace,
body=body
)
logging.info(f"Pod {namespace}/{pod_name} isolated")
except Exception as e:
logging.error(f"Failed to isolate pod: {e}")
def collect_pod_logs(self, namespace, pod_name):
"""Collect logs for forensic analysis"""
try:
logs = self.k8s_client.read_namespaced_pod_log(
name=pod_name,
namespace=namespace,
tail_lines=1000
)
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
log_file = f"/var/log/security/forensics/{namespace}-{pod_name}-{timestamp}.log"
with open(log_file, 'w') as f:
f.write(logs)
logging.info(f"Logs collected: {log_file}")
except Exception as e:
logging.error(f"Failed to collect logs: {e}")
def create_incident(self, incident_type, alert_data):
"""Create security incident ticket"""
incident = {
"type": incident_type,
"timestamp": datetime.now().isoformat(),
"alert_data": alert_data,
"status": "INVESTIGATING",
"severity": self.get_severity(incident_type)
}
# Integration with incident management system
self.send_to_incident_system(incident)
def get_severity(self, incident_type):
severity_map = {
"PRIVILEGED_CONTAINER": "HIGH",
"UNAUTHORIZED_IMAGE": "CRITICAL",
"SUSPICIOUS_NETWORK": "MEDIUM"
}
return severity_map.get(incident_type, "LOW")
def send_to_incident_system(self, incident):
"""Send incident to external system"""
# Implementation depends on your incident management system
logging.info(f"Incident created: {incident['type']} - {incident['severity']}")
if __name__ == "__main__":
handler = SecurityIncidentHandler()
# Process incoming alerts
handler.handle_privileged_container_alert({
"namespace": "production",
"pod": "suspicious-pod-123"
})
Best Practices Summary
Security Checklist
Essential security practices:
Image Security Checklist
- [ ] Use minimal, official base images
- [ ] Scan images for vulnerabilities
- [ ] Sign and verify images
- [ ] Implement supply chain security
- [ ] Regular image updates
Runtime Security Checklist
- [ ] Run containers as non-root
- [ ] Use read-only root filesystems
- [ ] Drop unnecessary capabilities
- [ ] Implement resource limits
- [ ] Enable security contexts
Network Security Checklist
- [ ] Implement network policies
- [ ] Use service mesh for encryption
- [ ] Segment network traffic
- [ ] Monitor network connections
- [ ] Restrict ingress/egress
Access Control Checklist
- [ ] Implement RBAC properly
- [ ] Use service accounts
- [ ] Rotate credentials regularly
- [ ] Audit access logs
- [ ] Follow least privilege
Monitoring Checklist
- [ ] Deploy security monitoring
- [ ] Set up alerting rules
- [ ] Implement incident response
- [ ] Regular security assessments
- [ ] Compliance reporting
Related Documentation
- Kubernetes Ingress - HTTP/HTTPS routing security
- Service Mesh - Advanced traffic security
- Certificate Management - TLS certificate automation
- Infrastructure Security - Overall security practices
- Monitoring - Security monitoring and alerting
This guide provides comprehensive container security practices from development to production deployment. Security should be integrated throughout the entire container lifecycle.