Container Security in 2025: The "Zero Trust" Reality
I recently watched a frantic 3:00 AM recovery operation where a misconfigured kubelet allowed a crypto-miner to hijack 40% of a client’s CPU cycles. The breach didn't happen because of a zero-day exploit in the kernel. It happened because the team assumed "isolated" meant "secure." It doesn't.
In the Norwegian hosting landscape, where Datatilsynet (The Norwegian Data Protection Authority) is rightfully aggressive about GDPR enforcement, relying on default Docker or Kubernetes configurations is professional negligence. If you are running workloads in Oslo or dealing with EU citizen data, your security posture needs to shift from "perimeter defense" to "runtime paranoia."
This guide isn't about basic linting. It is about how we architect resilience into the stack, using the same principles we apply to the CoolVDS infrastructure.
1. The Fallacy of the "Root" Container
By September 2025, running containers as root is inexcusable. Yet, docker run still defaults to root. When a process breaks out of a root-owned container, it hits the host kernel with root privileges. Game over.
You must enforce Rootless Containers and strict UID mapping. Here is the non-negotiable standard for your Dockerfiles:
# The Wrong Way
# FROM ubuntu:24.04
# CMD ["/bin/my-app"]
# The 2025 Standard
FROM alpine:3.21
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
WORKDIR /home/appuser
COPY --chown=appuser:appgroup . .
ENTRYPOINT ["./my-app"]
In Kubernetes, you enforce this at the Pod level using `securityContext`. If a pod tries to run as UID 0, the kubelet should kill it immediately.
apiVersion: v1
kind: Pod
metadata:
name: secure-nordic-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
runAsGroup: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: my-registry/app:v2.5
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
Pro Tip: SettingreadOnlyRootFilesystem: truedefeats 90% of script-kiddie attacks. If they can't write their payload to/tmpor/var, they can't execute it. For legitimate temp files, mount anemptyDirvolume.
2. Runtime Security: eBPF is the Sheriff
Static scanning (scanning images before deploy) is necessary but insufficient. You need to know what is happening now. In 2025, eBPF (Extended Berkeley Packet Filter) tools like Falco or Tetragon are standard for monitoring syscalls without killing performance.
We need to detect if a shell is spawned inside a container—a behavior that should essentially never happen in production.
Here is a Falco rule configuration optimized for a strict production environment:
- rule: Terminal shell in container
desc: A shell was used as the entrypoint for the container values
condition: >
spawned_process and container
and shell_procs and proc.tty != 0
and container_entrypoint
output: "Shell spawned in container (user=%user.name %container.info)"
priority: CRITICAL
When this rule triggers, your orchestration system should isolate the pod immediately. We utilize similar heuristics at the hypervisor level on CoolVDS to monitor for noisy neighbor anomalies, ensuring that one compromised VPS cannot impact the I/O stability of others.
3. The Supply Chain: SBOMs and Sigstore
If you don't know what is in your binary, you are deploying a mystery box. Software Bill of Materials (SBOM) is now a requirement for many enterprise contracts in Norway.
Use Syft to generate the SBOM and Grype to scan it against the vulnerability database. But more importantly, verify the signature. We use Cosign (part of Sigstore) to ensure the image deployed in Oslo is the exact byte-for-byte image built in your CI pipeline.
# Generate key pair
cosign generate-key-pair
# Sign the image
cosign sign --key cosign.key my-registry.com/app:v1.0.0
# Verify in your admission controller
cosign verify --key cosign.pub my-registry.com/app:v1.0.0
4. Network Policies: The "Schrems II" Firewalls
GDPR compliance isn't just about storage; it's about transit. A database pod should never accept connections from the public internet. It should only accept traffic from the backend API.
By default, Kubernetes allows all-to-all communication. This is dangerous. Implement a "Default Deny" policy and whitelist strictly.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
When you whitelist, consider latency. CoolVDS instances in Norway peer directly with NIX (Norwegian Internet Exchange). Ensure your ingress rules allow traffic from these low-latency local subnets while blocking broad ranges from high-risk geos.
5. Infrastructure Isolation: KVM vs. LXC
This is where the hardware meets the road. Many budget providers sell "System Containers" (LXC/OpenVZ) as VPS. In these setups, you share the kernel with the host and other customers. If a kernel exploit is found, isolation evaporates.
| Feature | Container Virtualization (LXC) | CoolVDS (KVM) |
|---|---|---|
| Kernel Isolation | Shared (High Risk) | Dedicated (High Security) |
| Resource Guarantee | Soft Limits | Hard Allocation |
| Custom Kernel Modules | No | Yes (WireGuard, eBPF) |
For high-security workloads, we exclusively use KVM. This allows you to run your own hardened kernel versions and ensures that a container escape only lands the attacker in your specific VM, not the provider's host node.
6. Practical Hardening Commands
Before you even install Docker or K8s, harden the underlying Linux host. These sysctl flags mitigate common network attacks and memory manipulation.
# /etc/sysctl.d/99-security.conf
# Restrict kernel pointer access
kernel.kptr_restrict = 2
# Hide kernel log buffer
kernel.dmesg_restrict = 1
# Prevent BPF JIT spraying attacks
net.core.bpf_jit_harden = 2
# Protect against SYN flood
net.ipv4.tcp_syncookies = 1
Apply these with sysctl -p. On CoolVDS NVMe instances, these settings are compatible with our optimized disk I/O schedulers, so you don't sacrifice throughput for security.
Final Thoughts on Compliance and Performance
Security is a trade-off. Every lock adds friction. However, modern tools like Cilium and eBPF have minimized the performance penalty of deep inspection. In 2025, there is no excuse for running unprivileged code as root or exposing internal services to the public mesh.
If you are building infrastructure that demands Norwegian data sovereignty, low latency to Oslo, and true hardware isolation, don't rely on shared-kernel solutions. Build your fortress on a foundation designed for it.
Ready to lock down your stack? Deploy a hardened KVM instance on CoolVDS today and test your defense-in-depth strategy against real-world metrics.