Docker 是一个开源的容器化平台,它能将应用程序和它所需的所有依赖、配置、库等,打包成一个轻量、可移植的容器,确保应用在任何环境中都能一致地运行,从根本上解决了“在我电脑上没问题”的经典难题。

核心原理

Docker 并非凭空创造出一种新的虚拟化技术,而是巧妙地利用了 Linux 内核已有的几个底层机制,将它们组合封装,提供了像虚拟机一样的体验,但更加轻量和高效。其核心原理主要基于三大支柱:

1. 命名空间 —— 实现“隔离”的错觉

命名空间的作用是为每个容器创建一份独立的系统资源视图,让容器内的进程以为自己是独占整个操作系统。这就像给每个容器的进程戴上“眼罩”,大家用着同一个内核,却互不可见。

关键的命名空间包括:

  • PID 命名空间:隔离进程编号。容器内的进程 PID 为 1,在宿主机上则是另一个普通 PID,形成独立进程树。
  • 网络命名空间:隔离网卡、IP、端口、路由表等,让每个容器拥有独立的网络栈。
  • 挂载命名空间:隔离文件系统挂载点,让容器拥有自己独立的根文件系统(/)。
  • UTS 命名空间:隔离主机名和域名,容器可以有自己的 hostname。
  • 用户命名空间:隔离用户和用户组,容器内的 root 用户可能只是宿主机上的一个普通用户。

2. 控制组 —— 实现“限制”的管家

控制组的作用是限制、审计和隔离进程组对物理资源的使用。如果说命名空间让容器“看不见”别的容器,那么 Cgroups 就确保了没有哪个容器能“霸占”所有资源。它可以精细控制 CPU 时间、内存使用量、磁盘 I/O 和网络带宽等,防止因一个容器出问题而导致整个宿主机瘫痪。

3. 联合文件系统 —— 实现“层叠”的镜像技术

联合文件系统是 Docker 镜像得以轻量、快速构建和分发的核心。它将不同目录挂载到同一个虚拟文件系统下,形成层次化结构

  • 镜像是由多个只读层(Read-Only Layer)叠加组成的,每一层都代表 Dockerfile 中的一条指令。拉取或构建时,相同的层可以被共享和复用,极大地节省了磁盘和网络开销。
  • 容器启动时,会在只读的镜像层之上,增加一个可写层(Read-Write Layer)。当你修改文件时,Docker 使用写时复制(Copy-on-Write)策略:如果要修改只读层的一个文件,会先将它复制到可写层再进行修改,不影响原始镜像层。删除容器时,只需丢掉这个可写层,非常干净。

三大核心概念

  • 镜像 (Image):静态的、只读的模板,类似盖房子的蓝图。
  • 容器 (Container):镜像的运行实例,类似根据蓝图盖好的、可以住人的房子。一个镜像可启动多个容器。
  • 仓库 (Registry):集中存放和分发镜像的地方,Docker Hub 是最大的公共仓库。

Docker 与传统虚拟机的区别

Docker 最大的设计差异在于:它与宿主机共享操作系统内核

  • 虚拟机:需要虚拟化完整的硬件,每个虚拟机运行独立的操作系统(Guest OS),非常笨重,启动慢,资源占用大。
  • Docker 容器:只是宿主机上的一个特殊进程,直接复用宿主机的 Linux 内核,没有独立的操作系统层。因此它极其轻量,可以实现秒级启动,资源开销也接近于零。

简单总结,Docker 正是通过 Namespace 实现隔离Cgroups 实现资源限制Union FS 实现高效的分层文件系统,最终将进程级的隔离打包成类似“轻量级虚拟机”的体验,让应用的分发和部署变得前所未有的简单和一致。