Docker in Production: Locking Down Containers Before You Get Hacked
Let’s be honest for a second. Most of you are running docker run as root, mapping the socket to the host, and hoping for the best. I’ve seen it in dev, and terrifyingly, I’ve seen it in production environments across Oslo. In 2016, "containerization" is the buzzword of the year, but the security model is often an afterthought. If you treat a container like a lightweight VM, you are going to get burned.
I recently audited a setup for a media firm in Bergen where a developer had mounted the host's root directory into a container for "debugging purposes." One compromised web app later, the attacker had full control of the host node. This isn't theoretical. If you are deploying Docker on shared hosting or weak infrastructure, you are exposing your kernel to the world. Here is how we lock it down, protecting your data and keeping the Datatilsynet off your back.
1. The Foundation: KVM Isolation is Non-Negotiable
Before we touch a single Docker config, look at where you are running it. If you are trying to run Docker inside an OpenVZ or LXC container provided by a cheap hosting company, stop. You are sharing a kernel with potentially hundreds of other customers. If their container escapes, your data is gone.
You need hardware virtualization. We built CoolVDS on KVM (Kernel-based Virtual Machine) for exactly this reason. With KVM, your kernel is yours. Docker exploits that target kernel panic or resource exhaustion (like fork bombs) are contained within your VPS, not propagated to the neighbors. In the Norwegian hosting market, where data integrity is paramount, relying on soft isolation is professional negligence.
2. The "Root" Problem: Enable User Namespaces
By default, the root user inside a Docker container is the actual root user on the host system. If a process breaks out of the container cgroup, it has root on your server. This is the biggest security flaw in default Docker installations today (version 1.12).
The fix is User Namespaces (userns-remap). This maps the container's root (UID 0) to a high-number, non-privileged user on the host kernel.
Here is how you configure this on a CentOS 7 or Ubuntu 16.04 LTS host. First, stop the daemon:
sudo service docker stop
Edit your Docker daemon configuration file, usually located at /etc/docker/daemon.json (if it doesn't exist, create it):
{
"userns-remap": "default"
}
When you restart Docker, it will create a user named dockremap. Now, even if an attacker manages to break out of the container as "root", the host kernel sees them as a nobody with zero privileges. This single change mitigates 90% of privilege escalation attacks.
3. Drop Capabilities: Principle of Least Privilege
Linux capabilities break down the "all-or-nothing" power of root into distinct units. A web server does not need to modify kernel modules (CAP_SYS_MODULE) or change system time (CAP_SYS_TIME). Yet, Docker gives containers a massive list of capabilities by default.
Pro Tip: Never use the --privileged flag unless you are writing low-level system tools. It effectively disables all security protections.
Instead, explicitly drop all capabilities and add back only what you need. Here is an example of running an Nginx container securely:
docker run -d \
--name secure-nginx \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--cap-add=SETUID \
--cap-add=SETGID \
--cap-add=CHOWN \
-p 80:80 \
nginx:1.10
This command strips the container naked of privileges. It can bind to port 80 and manage its own user IDs, but it cannot mount filesystems, audit logs, or reboot the host.
4. Restrict Resources to Prevent DoS
A container without limits is a Denial of Service (DoS) attack waiting to happen. I've seen Java applications consume every GB of RAM on a host, triggering the OOM (Out of Memory) killer which—Murphy's Law—usually kills the SSH daemon instead of the rogue container.
On CoolVDS NVMe instances, we give you incredibly fast I/O, but you still need to ensure one noisy container doesn't starve the others. Use cgroups limits:
docker run -d \
--memory="512m" \
--memory-swap="1g" \
--cpus="1.0" \
--pids-limit=100 \
my-app:latest
The --pids-limit flag (introduced recently in Docker 1.10) is vital. It prevents a fork bomb inside a container from crashing the entire host kernel.
5. Read-Only Filesystems
If your application is stateless (and it should be), it has no business writing to the container's root filesystem. Immutable infrastructure is the goal. Run your containers as read-only and use tmpfs for temporary files.
docker run --read-only --tmpfs /run --tmpfs /tmp -d my-app
If an attacker exploits a vulnerability in your application code, they cannot write a backdoor script or modify system binaries because the filesystem is literally locked.
Comparison: Default vs. Hardened
| Feature | Default Docker Run | Hardened Setup |
|---|---|---|
| User | Root (UID 0) | Unprivileged (UID 1000+) |
| Filesystem | Read-Write | Read-Only |
| Capabilities | Broad (AUDIT_WRITE, MKNOD, etc.) | Minimal (NET_BIND_SERVICE) |
| Isolation | Process Namespace | User Namespace Remapped |
Local Data & Latency
Finally, remember where your bits live. Under the new EU-US Privacy Shield framework and strict Norwegian interpretation of data handling, knowing exactly where your container host resides is critical. Hyperscalers often obscure this.
With CoolVDS, your instances are running on physical hardware in our datacenters, optimized for low latency to the NIX (Norwegian Internet Exchange). When you are hardening your stack, don't ignore the network latency. Secure connections (TLS) require handshakes; adding 40ms of latency by hosting outside the region makes your secure app feel sluggish. Our NVMe storage ensures that even when you enable heavy audit logging (which you should), your disk I/O won't become a bottleneck.
Final Thoughts
Security isn't a product; it's a process. Docker 1.12 has given us powerful tools like Swarm mode and cryptographic node identity, but the basics of kernel isolation remain your first line of defense. Don't build a fortress on a swamp.
Ready to run containers that don't keep you up at night? Spin up a KVM-based, security-hardened instance on CoolVDS today. We handle the infrastructure; you handle the code.