The Docker Rebellion: When Convenience Compromises Security

In self-hosting communities, Docker reigns supreme for its simplicity and vast image library. Yet one engineer’s decade-long struggle with its security flaws culminated in an ultimatum: Docker is banned from all routing machines and production environments under their control. This controversial stance stems from four fundamental design failures that transform containers from isolation tools into systemic vulnerabilities.

1. The Daemon That Hijacks Your System

"Docker thinks it owns the whole system. Every daemon startup rewrites your firewall rules without consent—chaining administrators to its networking model."

Docker overrides iptables policies by default, forcibly setting the FORWARD chain to DROP. Disabling this breaks container networking entirely. This proved catastrophic when Docker repeatedly disrupted BGP routing on the author's infrastructure, leading to its permanent exile from network-critical systems.

2. UID Isolation: The Broken Foundation

Containers run as host-level root by default, nulling Unix’s core security model. A compromised container equals a compromised host:
- Applications running as root in containers inherit host root privileges
- User ID collisions allow easy privilege escalation (e.g., UID 1000 inside container = your desktop user)

Enabling UID namespaces requires nuking all Docker state—and still groups containers under one namespace. "This isn’t isolation," the author notes, "it’s security theater."

3. PID 1: Where Zombies Roam Free

Docker runs applications as init (PID 1) by default, triggering two nightmares:

# Zombie processes accumulate indefinitely without a real init
$ ps aux | grep 'Z'  # Thousands of undead processes

Worse, PID 1 ignores termination signals due to SIGNAL_UNKILLABLE. The author recounts a Python app that swallowed SIGSEGV crashes and kept running—a ticking time bomb masked by Docker’s design.

4. The Docker Image Minefield

Popular images often embody anti-patterns:
- Running development servers (like Flask’s run()) in production
- Outdated OS layers with unpatched CVEs
- Root-executed services with no namespacing

"The vast image repository is a liability," warns the author. One maintainer dismissed concerns about a vulnerable Flask image with "it works"—epitomizing Docker’s culture of convenience over security.

Beyond the Big Four: IPv6 and Disk Bloat

Docker’s NAT-heavy model complicates IPv6 deployment, perpetuating IPv4 exhaustion. Meanwhile, accumulated image layers frequently consume disk space unchecked—a silent resource drain.

The Escape Plan: Alternatives to Docker’s Defaults

For non-reproducible workloads, the author advocates:

  1. Virtual Machines: Full isolation for Docker-dependent apps (like Immich)
  2. systemd-nspawn: Containerization with proper init, UID namespaces, and updatable OS images
  3. Traditional Deployment: When reproducibility isn’t critical

Docker only earns reprieve when:
- Reproducibility is mandatory (e.g., CI/CD pipelines)
- You build and maintain your own hardened images
- Containers run on dedicated hosts

"If your software forces Docker," the author concludes, "lock it in a VM. And maintainers: please offer non-Docker installs." As containerization evolves, this critique underscores that default settings can’t override operational vigilance.


Source: Docker Considered Harmful by a systems engineer documenting real-world security breaches, including cryptojacking via Jellyfin containers.