Console Login

Container Security in 2022: Hardening Docker & K8s for the Paranoid

Container Security in 2022: Hardening Docker & K8s for the Paranoid

Let’s be honest: default container configurations are a disaster waiting to happen. If you are still pulling node:latest and running your production apps as root, you aren't doing DevOps; you're playing Russian Roulette with your infrastructure. After the Log4j nightmare last winter, the patience for loose security postures has evaporated. I've spent the last week auditing clusters that were supposedly "secure," only to find privileged pods offering a red carpet to the host filesystem.

For those of us operating in Norway and the broader EEA, the stakes are higher. It's not just about keeping hackers out; it's about Datatilsynet (The Norwegian Data Protection Authority) and the strict realities of Schrems II. You can't just dump customer data into a US-managed cloud bucket anymore and hope for the best. Compliance is now a technical specification.

1. Drop Root. Now.

The obsession with running processes as PID 1 inside a container as root is the most common vulnerability I see. If an attacker manages to break out of the container runtime—and yes, runtime vulnerabilities happen—they are root on your host. Game over.

Modify your Dockerfiles. Create a specific user and group. It adds three lines of code and saves you a lifetime of headaches.

FROM alpine:3.15

# Create a group and user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Tell docker that all future commands should run as the appuser user
USER appuser

CMD ["./my-secure-app"]

In Kubernetes, enforce this at the Pod level using the SecurityContext. If a developer tries to deploy a container that needs root, the cluster should reject it outright.

apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: app
    image: my-app:1.4.2
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true

2. The Immutable Filesystem

Why does your application need write access to the entire OS? It doesn't. It usually needs to write to /tmp or a specific log directory. Everything else should be read-only. This effectively neutralizes a whole class of exploits where attackers download malicious scripts or modify binaries at runtime.

As seen in the YAML above, setting readOnlyRootFilesystem: true is a quick win. If your app crashes because it can't write to a config folder, fix the app, don't lower the shield.

3. Infrastructure Isolation: The CoolVDS Advantage

Software limits are great, but hardware isolation is the bedrock. Containers share the host kernel. This is efficient, but it means a kernel panic or a kernel exploit affects everyone. This is where your choice of VPS provider becomes a security decision.

At CoolVDS, we don't mess around with old-school OpenVZ containers where you are sharing kernel modules with a noisy neighbor. We use KVM (Kernel-based Virtual Machine) for our NVMe instances. Each CoolVDS VPS has its own isolated kernel. Even if a container inside your VPS is compromised, the attacker is trapped inside your virtual machine, not roaming our hypervisor.

Pro Tip: When benchmarking your VPS in Norway, check the "steal time" (st) in top. On oversold platforms, this spikes. On CoolVDS, we guarantee dedicated resources, ensuring that security scanning tools like ClamAV or Trivy don't choke your CPU when you need them most.

4. Capability Dropping

Linux divides the privileges traditionally associated with superuser into distinct units, known as capabilities. Does your web server need NET_ADMIN (network configuration) or SYS_TIME (changing the system clock)? Absolutely not.

Docker gives containers a default set of capabilities that is often too broad. Drop everything, then add back only what is strictly necessary.

docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx:stable-alpine

This "denylist by default" approach confuses attackers who expect standard tools to work. They try to run a network scan or mount a drive, and the kernel simply says "Permission Denied."

5. Supply Chain: Trust No One

In May 2022, we are seeing a massive uptick in supply chain attacks. Malicious packages in NPM and PyPI are being pulled into build pipelines automatically. The days of FROM node:latest are dead. You need deterministic builds.

  • Pin Versions: Use specific tags (e.g., node:16.15.0-alpine).
  • Use Digests: For high-security environments, pin the SHA256 hash. Tags can be overwritten; hashes cannot.
  • Scan on Push: Integrate tools like Trivy or Grype into your CI/CD pipeline. Fail the build if a Critical CVE is found.

6. Data Sovereignty and Network Latency

Security isn't just code; it's physics and law. Hosting your containers in a datacenter in Frankfurt or Virginia introduces latency and legal ambiguity. For Norwegian businesses, keeping data inside Norwegian borders is often a compliance requirement for GDPR.

CoolVDS infrastructure is physically located to optimize routing via NIX (Norwegian Internet Exchange). We see latency as low as 2-3ms from downtown Oslo. When you are running high-frequency API calls between microservices, that lack of latency translates to stability. Furthermore, knowing exactly where your physical drives spin (or in our case, where the NVMe chips flash) satisfies the strictest interpretation of data residency laws.

Final Thoughts

Securing containers is an iterative process. You start by dropping root, you move to read-only filesystems, and you end by ensuring your underlying infrastructure is as robust as your code. Don't let a misconfigured YAML file be the reason you're waking up at 3 AM on a Saturday.

If you need a sandbox to test these hardened configurations without risking your production environment, spin up a KVM-based instance. It takes less than a minute.

Deploy a Secure Test Instance on CoolVDS Now