The Myth of the "Lightweight VM"
Let’s be honest with ourselves. If you are running Docker in production right now, you are probably nervous. Last month's Dirty COW (CVE-2016-5195) exploit wasn't just another kernel bug; it was a harsh reminder that containers share the host kernel. If an attacker gains root inside a container and hits a kernel vulnerability, they own the host. Game over.
I see too many developers in Oslo and across Europe treating Docker containers like they are fully isolated Virtual Machines. They aren't. They are just fancy processes with cgroups and namespaces tape-wrapped around them. Efficiency is great, but efficiency without security is just negligence.
If you are deploying on bare metal or—heaven forbid—OpenVZ, you are exposing your infrastructure to unnecessary risk. Here is how we lock things down, from the Dockerfile to the kernel level, using the tools available to us in late 2016.
1. The Root of All Evil
By default, the process inside a Docker container runs as root. If that process breaks out, it has root privileges on your host. This is the default behavior of Docker 1.12, and it is dangerous.
You need to enforce the Principle of Least Privilege. Create a user inside your image and switch to it.
FROM centos:7
# Create a group and user
RUN groupadd -r appuser && useradd -r -g appuser appuser
# Install dependencies (as root)
RUN yum -y install epel-release && yum -y install nginx
# Switch to non-root user
USER appuser
CMD ["nginx", "-g", "daemon off;"]If you try to bind port 80 as appuser, it will fail because non-root users cannot bind ports under 1024. Use a reverse proxy like Nginx on the host, or map high ports (e.g., 8080) in your container.
2. Drop Kernel Capabilities
Linux kernel capabilities break down the power of "root" into distinct privileges. Does your Node.js application really need CAP_NET_ADMIN (network configuration) or CAP_SYS_MODULE (loading kernel modules)? Absolutely not.
Docker gives containers a broad set of capabilities by default. You should drop them all and add back only what you need. This drastically reduces the attack surface if a compromise occurs.
docker run --d -p 8080:8080 \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--name secure-app \
my-secure-image:v1This command strips all privileges. Even if an attacker gets a shell, they can't change network settings, mount filesystems, or mess with the audit logs.
3. Isolation: Why KVM is Non-Negotiable
Here is where the infrastructure choice matters. Many budget VPS providers use OpenVZ or LXC. In those environments, you are sharing a kernel not just with your own containers, but with other customers on the same physical node. If a neighbor triggers a kernel panic or an exploit like Dirty COW, your data is at risk.
This is why we built CoolVDS strictly on KVM (Kernel-based Virtual Machine). KVM provides hardware-level virtualization. Your VPS has its own kernel.
Pro Tip: Run your Docker hosts on KVM instances. If a container escapes the namespace, it is trapped inside your VPS. It cannot reach the hypervisor or other tenants. This is the "Defense in Depth" strategy required for compliance with Norwegian data standards and the looming GDPR regulations.
4. Read-Only Filesystems
Immutability is a core tenant of the DevOps philosophy. Your containers should be stateless. If an attacker compromises your web app, the first thing they want to do is download a backdoor script.
Stop them by making the root filesystem read-only.
docker run --read-only \
-v /app/data:/data:rw \
--tmpfs /run \
--tmpfs /tmp \
my-appIn this configuration, no files can be written to the container's root. We use --tmpfs for temporary directories that need writing, which stores data in RAM, ensuring it vanishes upon restart. This frustrates attackers and prevents persistence.
5. Limit Resources (Prevent DoS)
A compromised container can become a noisy neighbor to your other services, consuming 100% CPU or exhausting RAM. Docker 1.12 allows us to set hard limits.
version: '2'
services:
web:
image: nginx
mem_limit: 512m
cpus: 0.5
restart: alwaysUsing a docker-compose.yml file (v2 format is current standard), we ensure this container never takes more than half a CPU core or 512MB RAM. This keeps your CoolVDS instance responsive even under heavy load.
6. Network Segmentation
Don't use the default bridge network. Containers on the default bridge can communicate with each other by IP address effortlessly. Instead, create user-defined networks to isolate tiers.
# Create backend network
docker network create --driver bridge backend-net
# Run DB only on backend
docker run -d --net=backend-net --name db redis
# Run App on backend (can talk to db) and frontend
docker run -d --net=backend-net -p 80:80 --name app my-appNow, if you have a separate frontend container not attached to backend-net, it cannot physically route packets to your Redis database.
Conclusion: Trust No One, Verify Everything
The tech landscape in 2016 is moving fast. With the Datatilsynet (Norwegian Data Protection Authority) keeping a close eye on data privacy, and the EU-US Privacy Shield replacing Safe Harbor, where your data lives and how it is isolated matters more than ever.
Docker is a powerful tool, but out of the box, it prioritizes usability over security. By dropping capabilities, enforcing user limits, and running on true hardware virtualization like KVM, you mitigate 99% of the risks.
Don't let shared-kernel hosting be your single point of failure. Deploy your hardened Docker environment on a CoolVDS KVM instance today. We provide the raw NVMe performance and true isolation you need to keep your Norwegian clients safe.