Containers have revolutionized application deployment, but they also introduce new security challenges. Misconfigured Docker containers and Kubernetes clusters are among the most common targets for attackers in 2026. This guide covers comprehensive security practices for both Docker and Kubernetes environments.
Docker Security
1. Image Security
# Scan images for vulnerabilities with Trivy
sudo apt install trivy
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL myapp:latest
# Build minimal images with multi-stage builds
# Dockerfile
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o server .
FROM scratch
COPY --from=builder /app/server /server
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
USER 1000:1000
ENTRYPOINT ["/server"]
# Sign images with Docker Content Trust
export DOCKER_CONTENT_TRUST=1
docker push myregistry/myapp:latest
2. Runtime Security
# Run containers with least privilege
docker run -d \
--name webapp \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--security-opt no-new-privileges:true \
--security-opt seccomp=default.json \
--user 1000:1000 \
--memory 512m \
--cpus 1.0 \
--pids-limit 100 \
--network custom-net \
myapp:latest
# Docker daemon hardening
# /etc/docker/daemon.json
{
"icc": false,
"userns-remap": "default",
"no-new-privileges": true,
"live-restore": true,
"userland-proxy": false,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Kubernetes Security
3. RBAC Configuration
# Minimal RBAC for a developer
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: developer-role
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: development
name: developer-binding
subjects:
- kind: User
name: developer@company.com
roleRef:
kind: Role
name: developer-role
apiGroup: rbac.authorization.k8s.io
4. Pod Security Standards
# Restricted Pod Security Standard
apiVersion: v1
kind: Pod
metadata:
name: secure-app
namespace: production
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "250m"
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 100Mi
5. Network Policies
# Default deny all traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Allow only specific traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: webapp-policy
namespace: production
spec:
podSelector:
matchLabels:
app: webapp
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: nginx-ingress
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to: # Allow DNS
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
6. Secrets Management
# Use external secrets operator instead of native K8s secrets
# Native secrets are base64 encoded, NOT encrypted!
# Encrypt secrets at rest in etcd
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: $(head -c 32 /dev/urandom | base64)
- identity: {}
# Use sealed-secrets for GitOps
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
kubectl apply -f sealed-secret.yaml
7. Runtime Monitoring with Falco
# Install Falco
curl -fsSL https://falco.org/repo/falcosecurity-packages.asc | sudo gpg --dearmor -o /usr/share/keyrings/falco-archive-keyring.gpg
sudo apt update && sudo apt install falco
# Custom Falco rules
- rule: Shell in Container
desc: Detect shell execution in containers
condition: >
spawned_process and container and
proc.name in (bash, sh, zsh, dash)
output: >
Shell executed in container
(user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname)
priority: WARNING
- rule: Sensitive File Access
desc: Detect access to sensitive files
condition: >
open_read and container and
fd.name in (/etc/shadow, /etc/passwd, /proc/self/environ)
output: >
Sensitive file accessed in container
(file=%fd.name container=%container.name)
priority: CRITICAL
# Start Falco
sudo systemctl enable falco
sudo systemctl start falco
sudo journalctl -u falco -f
Recommended Reading
Master container and cloud security:
Download our Container Security Cheat Sheet for a printable quick-reference guide.