Docker 很奇怪

工程师们解析为什么 Docker 会显得“奇怪”,追溯它如何把 namespaces 和 cgroups 等 Linux 原语叠加成自包含机器的幻象,以及早期设计选择——例如 root 运行的 daemon、基于 Go 的运行时和 Dockerfile 语法——如何塑造了它的力量与怪癖。参与者将 Docker 与 Podman、Incus 和 Firecracker 等替代方案进行对比,讨论 rootless 运行、网络模型,以及 Go 相比 C 或 Rust 是否适合底层容器工作。大家普遍认为,Docker 真正的突破在于开发者体验、镜像分层和中心化仓库;这些彻底改变了软件的打包与部署方式,尽管生态已经转向更轻量或更安全的运行时。

Docker 的起源、历史与影响

  • Docker 源自一家 PaaS 公司内多年围绕 vserver/openvz/LXC 和联合文件系统的实验,后来又从那家 PaaS 业务中转向。
  • 提到的关键创新包括:Dockerfile 和镜像分层(快速、可缓存的构建)、中心化镜像仓库,以及不懈的布道和演示。
  • 许多评论者说,它改变了他们的职业和工作流程,取代了 Vagrant、定制的 LXC/Zones 配置、冗长的配置指南,以及“在我机器上能跑”的问题。
  • 有人认为它的主要价值在于让内核原语(namespaces、cgroups、chroot)变得极其容易使用;也有人更强调镜像仓库和生态势能。

语言选择与运行时设计

  • 最初项目使用的是 Python;Docker 后来选择 Go,是为了静态二进制、跨“部落”的采用,以及便于贡献者参与。
  • 创始人和其他人都认为 Go 处理底层容器工作时(clone、namespaces)很别扭,需要 C 适配层和各种变通办法,但在当时仍是正确的权衡。
  • 线程和 goroutine 的行为带来了细微 bug(例如 namespaces 没有被清理、难以处理线程绑定的系统调用)。
  • 关于 Rust 的争论:有人说如果是今天,他们会为运行时选择 Rust 或 C;也有人认为 Rust 的开发速度和 borrow checker 让它对许多团队来说不现实。

Daemon、root 与权限模型

  • Docker 的 client–server daemon 模型争议很大:
    • 批评者:它让权限变复杂,使 Docker socket ≈ root,与防火墙相冲突,在多用户系统上也很别扭。
    • 支持者:在 Linux/容器早期,这是一种务实方式,既能让非 root 用户管理容器,也能统一 Mac/Windows/Linux 的用户体验。
  • 如今已经有 rootless 模式,但推出得较晚;Podman 和其他工具因默认无 daemon/默认 rootless 而获得了关注。

网络与术语

  • 对 Docker 的“bridge”网络存在强烈分歧:
    • 网络管理员认为,与传统桥接和广播域相比,这个术语具有误导性,而且默认设置(NAT、DNS 调整)会让运维团队感到意外。
    • 其他人坚持认为,这些术语与底层 Linux bridge 设备相符,而 Docker 网络主要是为了容器间连通性,NAT 只是便利功能。

商业化与生态

  • 几条评论分析了 Docker 的商业困境:开源团队与企业团队之间的文化分裂、缺乏一个强势的单一产品“独裁者”、以及把核心开发者工具变现本身就很困难。
  • 有人认为忽视了某些企业需求,为竞争对手留下了空间;也有人说这些并不是真正的商业阻碍。

当前使用、替代方案与演进

  • Docker 仍然是许多开发和 CI 工作流的核心,尤其是通过 Compose。
  • 一些用户已经迁移到 Podman、Incus、LXC/systemd-nspawn,或基于 Firecracker 的方案,以获得更好的隔离性或更简单的安全属性。
  • 新工具(例如 Dagger、Range)建立在容器/镜像理念之上,优化 CI 和按需执行,而无需 daemon 或传统仓库。

学习与教育

  • 对于是否应该教授 Docker,存在分歧:一些人认为 Dockerfile 语法很简单,可以轻易交给工具/LLMs;另一些人强调,理解容器与虚拟机的区别、namespaces、分层和缓存,才是更重要的教育价值。