Docker is weird

Engineers unpack why Docker feels “weird,” tracing how it layers Linux primitives like namespaces and cgroups into the illusion of self-contained machines and how early design choices—such as a root-running daemon, Go-based runtime, and Dockerfile syntax—shaped both its power and its quirks. Participants contrast Docker with alternatives like Podman, Incus, and Firecracker, debating rootless operation, networking models, and the suitability of Go versus C or Rust for low-level container work. There’s broad agreement that Docker’s real breakthroughs were its developer experience, image layering, and central registry, which fundamentally changed how software is packaged and deployed even as the ecosystem has moved on to lighter or more secure runtimes.

Origin, history, and impact of Docker

  • Docker grew out of years of experimentation with vserver/openvz/LXC and union filesystems inside a PaaS company, then pivoted from that PaaS.
  • Key innovations called out: Dockerfiles and image layering (fast, cacheable builds), a centralized image registry, and relentless evangelism and demos.
  • Many commenters say it transformed their careers and workflows, replacing Vagrant, bespoke LXC/Zones setups, long config guides, and “works on my machine” problems.
  • Some argue the main value was making kernel primitives (namespaces, cgroups, chroot) trivially accessible; others emphasize the registry and ecosystem momentum.

Language choice and runtime design

  • The original project used Python; Docker later chose Go for static binaries, cross-“tribe” adoption, and contributor friendliness.
  • Creator and others agree Go was awkward for low-level container work (clone, namespaces), requiring C shims and workarounds, but still the right tradeoff then.
  • Threading and goroutine behavior caused subtle bugs (e.g., namespaces not cleaned up, difficulty with thread-affine syscalls).
  • Debate over Rust: some say today they’d pick Rust or C for a runtime; others argue Rust’s development speed and borrow checker make it impractical for many teams.

Daemon, root, and permissions model

  • Docker’s client–server daemon model is heavily debated:
    • Critics: complicates permissions, makes Docker socket ≈ root, fights with firewalls, awkward on multi-user systems.
    • Defenders: in early Linux/container days it was the pragmatic way to let non-root users manage containers and unify Mac/Windows/Linux UX.
  • Rootless modes now exist but were late; Podman and others gained traction by being daemonless/rootless by default.

Networking and terminology

  • Strong disagreement about Docker’s “bridge” networks:
    • Network admins argue the term is misleading vs traditional bridging and broadcast domains, and that defaults (NAT, DNS tweaks) surprise ops teams.
    • Others insist the terminology matches the underlying Linux bridge devices and that Docker networks are primarily for intra-container connectivity, with NAT just a convenience.

Commercialization and ecosystem

  • Several comments analyze Docker’s business struggles: cultural split between open-source and enterprise teams, lack of a single strong product “dictator,” and difficult monetization of a core developer tool.
  • Some believe ignoring certain enterprise needs opened space for competitors; others say those issues weren’t the real commercial blockers.

Current usage, alternatives, and evolution

  • Docker remains central to many dev and CI workflows, especially via Compose.
  • Some users have migrated to Podman, Incus, LXC/systemd-nspawn, or Firecracker-based setups for better isolation or simpler security properties.
  • New tools (e.g., Dagger, Range) build on container/image ideas to optimize CI and on-demand execution without daemons or traditional registries.

Learning and education

  • Split views on teaching Docker: some say Dockerfile syntax is trivial and easily offloaded to tools/LLMs; others stress understanding containers vs VMs, namespaces, layering, and caching as the real educational value.