Containerization has revolutionized how we deploy and manage applications. Docker and Kubernetes have become the de facto standards for running microservices, CI/CD pipelines, and cloud-native applications. But with this rapid adoption comes a critical challenge: security.
Containers share the host kernel, run with elevated privileges by default, and pull images from public registries that may contain vulnerabilities. A single misconfigured container can become an entry point for attackers to compromise your entire infrastructure. In 2023, over 76% of organizations running containers experienced at least one security incident, and the average cost of a container breach exceeded $4 million.
This guide covers practical container security from the ground up: Docker image hardening, Kubernetes access control, runtime protection, and compliance strategies. Whether you're running a small deployment or managing thousands of pods, these best practices will help you build secure, resilient containerized infrastructure.
Use Minimal Base Images
The smaller your container image, the smaller your attack surface. Official Alpine Linux images (5MB) contain far fewer packages—and therefore fewer vulnerabilities—than full Ubuntu images (70MB+).
# Bad: Full Ubuntu base
FROM ubuntu:22.04
# Good: Minimal Alpine base
FROM alpine:3.19
# Better: Distroless for production
FROM gcr.io/distroless/static-debian12
Distroless images contain only your application and runtime dependencies—no shell, no package manager, no tools an attacker could use.
Scan Images for Vulnerabilities
Never deploy an image without scanning it first. Tools like Trivy, Grype, and Clair analyze images for known CVEs.
# Scan image before deployment
trivy image myapp:latest
# Fail CI/CD builds on HIGH/CRITICAL vulnerabilities
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest
Integrate scanning into your CI/CD pipeline. A vulnerability that's caught in development costs far less to fix than one discovered in production.
Use Trusted Registries
Public Docker Hub images are convenient but risky. Over 20% of popular Docker Hub images contain high-severity vulnerabilities. Use private registries (Harbor, AWS ECR, Google Artifact Registry) and enable content trust to verify image signatures.
# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1
# Only signed images can be pulled/pushed
docker pull myregistry.com/myapp:latest
Run as Non-Root User
Containers run as root by default. If an attacker escapes the container, they have root access to the host. Always specify a non-root user in your Dockerfile:
# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Switch to non-root user
USER appuser
# Application runs as appuser, not root
CMD ["./myapp"]
Enable User Namespaces
User namespaces remap container UIDs to unprivileged host UIDs. Root inside the container (UID 0) maps to an unprivileged UID on the host.
# Enable user namespaces in Docker daemon
{
"userns-remap": "default"
}
# Restart Docker
sudo systemctl restart docker
Apply Security Profiles
Seccomp (Secure Computing Mode) restricts which system calls a container can make. AppArmor and SELinux provide mandatory access control.
# Run with default seccomp profile
docker run --security-opt seccomp=/path/to/seccomp.json myapp
# AppArmor profile
docker run --security-opt apparmor=docker-default myapp
# SELinux context
docker run --security-opt label=level:s0:c100,c200 myapp
The default Docker seccomp profile blocks ~44 dangerous syscalls (reboot, kernel module loading, etc.). Custom profiles can tighten this further based on your application's needs.
Multi-Stage Builds
Build tools (compilers, npm, pip) shouldn't exist in production images. Multi-stage builds let you compile in one stage and copy only the binary to a minimal runtime image.
# Stage 1: Build
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# Stage 2: Runtime (only the binary)
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/myapp /
CMD ["/myapp"]
Never Store Secrets in Images
Hardcoded API keys, passwords, or certificates in Dockerfiles end up in image layers permanently—even if you delete them in a later layer.
# Bad: Secret in image layer
RUN echo "API_KEY=secret123" > /app/config
# Good: Mount secrets at runtime
docker run --secret id=apikey,src=/path/to/secret myapp
# Better: Use Kubernetes secrets or external vaults
kubectl create secret generic api-key --from-literal=key=secret123
RBAC: Role-Based Access Control
Kubernetes RBAC controls who can do what in your cluster. The principle of least privilege applies: grant only the minimum permissions required.
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp-sa
namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: myapp-role
namespace: production
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: myapp-binding
namespace: production
subjects:
- kind: ServiceAccount
name: myapp-sa
roleRef:
kind: Role
name: myapp-role
apiGroup: rbac.authorization.k8s.io
Network Policies
By default, all pods can communicate with all other pods. Network policies enforce segmentation.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
This policy ensures the backend only accepts traffic from the frontend on port 8080 and only sends traffic to the database on port 5432. Everything else is denied.
Pod Security Standards
Kubernetes Pod Security Standards (PSS) replaced Pod Security Policies in v1.25. Three levels: Privileged, Baseline, Restricted.
# Enforce restricted policy on namespace
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
Secrets Management
By default, Kubernetes stores secrets in etcd unencrypted. Enable encryption:
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}
Falco: Runtime Threat Detection
Falco monitors system calls and detects anomalous behavior in real-time.
# Detect shell execution in container
- rule: Shell spawned in container
desc: A shell was spawned in a container
condition: >
container and proc.name in (bash, sh, zsh)
output: >
Shell spawned in container (user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
priority: WARNING
Deploy Falco as a DaemonSet to monitor all nodes:
helm install falco falcosecurity/falco \
--set falco.grpc.enabled=true \
--set falco.grpcOutput.enabled=true
Image Scanning and Compliance
Run continuous scanning on running containers, not just at build time. Vulnerabilities are discovered daily.
# Trivy Operator: Scan running workloads
kubectl apply -f https://raw.githubusercontent.com/aquasecurity/trivy-operator/main/deploy/static/trivy-operator.yaml
# View vulnerability reports
kubectl get vulnerabilityreports -A
FADP Compliance for Containerized Workloads
Switzerland's Federal Act on Data Protection (FADP) provides strong privacy guarantees. Hosting Kubernetes clusters in Switzerland ensures:
• Data residency: All container data (images, logs, secrets) stays in Switzerland
• No third-party access: Swiss law prohibits foreign government access without Swiss court approval
• Transparency: Swiss data centers must disclose data handling practices
This is critical for regulated industries (healthcare, finance) running sensitive workloads in containers.
Data Sovereignty for Kubernetes Clusters
US-based cloud providers (AWS, GCP, Azure) are subject to the CLOUD Act, which allows US authorities to access data regardless of where it's stored. Swiss-hosted Kubernetes clusters are outside this jurisdiction.
For organizations running multi-tenant SaaS platforms or handling EU customer data, Swiss infrastructure provides legal protection that US clouds cannot guarantee.
Infrastructure Reliability
Swiss data centers average 99.95% uptime. Kubernetes control planes hosted in Switzerland benefit from:
• Redundant power (N+1 UPS, dual grid connections)
• Low-latency networking (10Gbps+ backbone)
• Physical security (biometric access, 24/7 monitoring)
Container orchestration requires reliable infrastructure. Kubernetes node failures or network partitions can cause cascading outages. Swiss infrastructure minimizes these risks.
Image Security:
✅ Use minimal base images (Alpine, distroless)
✅ Scan all images for vulnerabilities (Trivy, Grype)
✅ Pull from trusted private registries
✅ Enable Docker Content Trust
✅ Pin base images to specific digests
Container Runtime:
✅ Run containers as non-root user
✅ Enable user namespaces
✅ Apply seccomp/AppArmor/SELinux profiles
✅ Drop unnecessary capabilities
✅ Use read-only root filesystems
Kubernetes Security:
✅ Enable RBAC, enforce least privilege
✅ Create dedicated service accounts
✅ Implement network policies
✅ Enforce Pod Security Standards (Restricted)
✅ Encrypt secrets at rest
✅ Use external secret stores
✅ Enable audit logging
Monitoring:
✅ Deploy Falco for runtime threat detection
✅ Continuous image scanning (Trivy Operator)
✅ Centralized logging (ship to ELK/Loki)
✅ Alert on policy violations
Container security isn't a checkbox—it's a continuous process. Vulnerabilities are discovered daily, configurations drift, and attackers evolve their techniques. The practices outlined here provide a strong foundation: minimal images, least-privilege access, runtime monitoring, and compliance-focused infrastructure.
If you're running production Kubernetes clusters, consider where your infrastructure is hosted. Swiss data centers offer legal protections and infrastructure reliability that align with security-first container deployments. FADP compliance, data sovereignty, and robust physical infrastructure make Switzerland an ideal jurisdiction for containerized workloads handling sensitive data.
Secure your containers, monitor your clusters, and choose infrastructure that reinforces—not undermines—your security posture.
Ready to deploy secure containerized infrastructure? Explore our dedicated servers for Kubernetes hosting, check out our VPS options for development clusters, or contact us for custom infrastructure solutions.