Console Login

Container Security in 2020: Surviving the runc Apocalypse on Norwegian Soil

Container Security in 2020: Surviving the runc Apocalypse on Norwegian Soil

Let’s cut the marketing fluff. If you are running Docker containers as root in production today, you are negligent. Earlier this year, CVE-2019-5736 (the runc container breakout) showed us exactly how fragile the barrier between a container and the host kernel really is. If an attacker compromises your container process, they can overwrite the host runc binary and gain root execution on the host node. Game over.

For those of us managing infrastructure in Norway, the stakes are double. We aren't just protecting uptime; we are answering to Datatilsynet. Under GDPR, a breach caused by a known configuration negligence isn't just an oopsie; it’s a percentage of your global revenue. I have seen too many ``latest`` tags and default configurations in production environments across Oslo. It stops today.

This guide isn't about buying expensive security suites. It is about applying the fundamental isolation principles using tools available right now in late 2019.

1. The Root Problem (Literally)

By default, a process inside a Docker container runs as PID 1 with root privileges. If that process escapes, it is root on your server. The fix is trivial, yet rarely applied.

Stop writing Dockerfiles that end with CMD. Create a specific user. Here is how we enforce this in our base images for CoolVDS internal tooling:

FROM alpine:3.10

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

# Move to a working directory
WORKDIR /app

# Copy binary
COPY --chown=appuser:appgroup my-binary .

# Switch to non-root user
USER appuser

CMD ["./my-binary"]

When you define USER appuser, even if the application code has a Remote Code Execution (RCE) vulnerability, the attacker lands in a shell with limited permissions. They cannot modify system binaries or bind to privileged ports (below 1024).

2. Immutability is Your Friend

Containers are ephemeral. They should be treated as such. If your application gets hacked, the attacker will often try to download a payload (like a cryptominer) or modify a configuration file. Make their life miserable by mounting the filesystem as read-only.

In Docker:

docker run --read-only -v /my/data:/data:rw my-image

In Kubernetes (1.16+), utilize the Security Context:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  containers:
  - name: app
    image: my-image:1.4.2
    securityContext:
      readOnlyRootFilesystem: true
    volumeMounts:
    - mountPath: /tmp
      name: tmp-volume
  volumes:
  - name: tmp-volume
    emptyDir: {}

Note the /tmp mount. Many apps crash if they can't write temporary files. Give them an emptyDir volume for scratch space, but keep the root locked down.

3. The Double-Isolation Strategy: KVM + Docker

Here is the hard truth about shared container platforms: Kernel sharing is risky. If you are using a "Container-as-a-Service" provider where your pods run alongside another customer's pods on the same kernel, you are trusting the hypervisor's seccomp profiles with your life. The runc exploit proved that this trust can be misplaced.

Architect's Note: This is why serious DevOps teams in the Nordics prefer running their container clusters on KVM-based VPS instances, like CoolVDS. With KVM, you have a hardware-level virtualization boundary. If a container escapes to the host OS, it escapes to your Guest OS, not the physical node shared by 500 other customers.

When you deploy a VPS Norway instance on CoolVDS, you get your own kernel. You can tune sysctl parameters for network hardening without asking for permission.

4. Network Policing: Don't Talk to Strangers

By default, all pods in a Kubernetes cluster can talk to each other. Your frontend web server has no business connecting to your Redis backend's admin port, and certainly not to the metadata service.

In 2019, if you aren't using a CNI plugin that supports NetworkPolicies (like Calico or Weave Net), you are wrong. Here is a default "Deny All" policy you should apply to every namespace immediately:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Then, whitelist only what is needed. This prevents lateral movement. If an attacker breaches the frontend, they are stuck in a padded cell.

5. Supply Chain: Scan Before You Push

You verify your code, but do you verify your base OS? Alpine and Debian release security patches constantly. If your CI/CD pipeline pushes an image built on a 6-month-old node:10 base, you are deploying vulnerabilities.

Integrate a scanner like Clair or Trivy (which is gaining serious traction lately) into your Jenkins or GitLab CI pipeline. Fail the build if critical CVEs are found.

# Example Trivy scan command in CI
$ trivy --exit-code 1 --severity CRITICAL my-app:latest

Why Infrastructure Matters

Security is layers. Your code is the first layer. The container config is the second. The infrastructure is the foundation. High-performance security scanning and encryption add overhead. Doing full TLS termination inside containers and running real-time intrusion detection requires CPU cycles and fast I/O.

This is where the hardware underneath matters. On CoolVDS, we use enterprise NVMe storage. When you run a heavy docker build or a vulnerability scan against a 2GB image, the NVMe I/O allows it to finish in seconds, not minutes. Slow storage tempts developers to skip security scans because "it takes too long." Don't let latency compromise security.

Furthermore, keeping your data in Norway (on servers physically located in Oslo) simplifies your GDPR compliance stance significantly compared to relying on US-owned cloud giants where the legal ground is shifting.

Final Checklist for 2020

  • [ ] User: Are you running as non-root?
  • [ ] Filesystem: Is root read-only?
  • [ ] Network: Is a Deny-All NetworkPolicy active?
  • [ ] Host: Are you isolated on a KVM VPS?

Do not wait for the next CVE to hit the headlines. Audit your Dockerfiles today. If you need a sandbox to test these hard-hitting configurations without risking your production node, spin up a CoolVDS instance. It takes 55 seconds, and you get the raw power needed to secure your stack properly.