我有一个程序员朋友,他每年情人节都要送女朋友一台服务器。

他说:“谁不想在过节当天收到一台 4核8g 的服务器呢?”

“万一对方不要,我还能留着自己用。” 给他一次过节的机会,他能把浪漫玩的明明白白。
所以今年情人节,他自己一个人过。
太痛了,是那种布洛芬都不知道他哪里痛的痛。

虽然人跑了,但起码还有服务器陪着他,但屏幕前依然单身的你呢? 你连服务器都没有。那么问题就来了,你买过服务器吗?看着云厂商各种产品是不是有点懵。
你知道 ecs,vps,docker 容器 是什么吗?它们有啥区别呢?

图片

我们今天来聊聊这个话题。

物理服务器是什么?

我的柜子里有一台大学时候用的废弃电脑,自带 cpu、 内存等硬件和操作系统,根据一些教程视频,是可以做成服务器的。

像这样一台看得见摸得着的机器,其实就是云厂商页面里提到的物理服务器物理机。不同厂商叫法不同,有的厂商叫它独立服务器

跟家里电脑不一样的是,云厂商的机器性能更好,核数更高,还有专业的机房和空调伺候着。那既然这样,是不是就不需要买云厂商的服务器呢?

糊涂啊,一台家用电脑跑起来 50 瓦,一年下来电费都好几百,还得花精力伺候着不让它关机,还真不如买别人家的划算。

但问题又来了,云厂商的物理服务器一般都是核数较高,很多时候我们根本不需要这么高配的机器。怎么办呢?这一点云厂商当然也考虑到了。

vps 和 ecs 是什么

云厂商一般会将一台物理服务器分割成多个虚拟机。它跟我们在 windows 用 VMwareVirtualBox 建的虚拟机其实是一回事。每个虚拟机都拥有独立的操作系统、资源(比如 CPU、内存、存储空间)和公网 IP 地址。然后对外出售,这样的虚拟机就是所谓的 VPS(Virtual Private Server,虚拟专用服务器)。

图片

VPS

但传统 VPS 有个缺点,不支持用户自主升降级,它的资源是预先分配的,不易动态调整。举个例子,假设你买了 1c1g 的服务器,想在页面上点点两下升级成 2c2g,这在传统 VPS 里是不支持的。如果给 VPS 加入自主升降级的功能,那它就成了 ECS(Elastic Compute Service,弹性计算服务)

图片

ECS支持自主升降级

用户可以根据需要随时调整 CPU、内存、磁盘和带宽,主打一个弹性。我们可以利用 ecs 学习 linux 命令,部署个人博客,做私人云盘存储,甚至可以将自己做的游戏部署到 ecs 上邀请朋友来玩。

图片

ecs的用途

docker 容器 是什么

买了 ecs 后,我们一般会开始部署自己的软件应用。机器少的时候手动部署问题不大,机器多了后各种问题就来了,其中最明显的就是,ecs 之间,如果底层操作系统不同,比如有些是 ubuntu,有些是 centos,部署应用的时候就会有各种环境问题。如果能让软件带着操作系统环境一起去部署就好了,最简单的方案是将软件和操作系统一起打包成虚拟机部署在 ecs 中。但这样就成了在 ECS(也就是虚拟机)中再运行一个完整的虚拟机,太重了。有解法吗?

图片

虚拟机上再运行一个虚拟机

有。既然多加一个操作系统太重,那我就只打包软件和系统依赖库加配置就好了。然后将这部分系统文件挂到 ecs 的操作系统下,利用一个叫 Namespace 的能力让它看起来就像是一个独立操作系统一样。再利用一个叫 Cgroup 的能力限制它能使用的计算资源。这就省掉了一层笨重的操作系统,同时还让软件轻松跑在各类操作系统上。这就是我们常说的 Docker 容器技术

图片

Docker容器是什么

总的来说就是,物理服务器上跑 ecs,ecs 跑 Docker 容器。多个 Docker 容器共享一个 ecs 实例 操作系统内核。

图片

ecs和docker容器的关系

服务器怎么选

现在我们了解完他们的区别了,但服务器款式那么多,我们怎么选?如果你是小公司老板或个体创业者,想要好一点的物理机又不想自建机房,那可以考虑买独立服务器。

如果你是像我一样的个人开发者,或者是学生,那无脑冲云服务器 ecs。有了它,我们可以很方便的在上面部署 docker 容器,平时做做实验,部署博客,完全够用了。

图片

容器里跑应用

这时候问题很多的小明就要问了,为什么不选择大厂商的云服务器?是用不起吗?喂喂喂,怎么说话呢? 不是大厂云服务器用不起,而是小厂商的更有性价比。就以同样是香港 1 核 1g 的 ecs 为例,小厂商一个月只要 1 碗红烧牛肉面。大厂商则要 3 碗。

同样是 24 核物理服务器,小厂商千把块搞定,大厂商就是它的好几倍。

这省下来的钱,能买多少份 19 块 9 5条的南极人内裤?

这时候问题很多的小明就又要问了,为什么要选香港服务器?大陆的不是更便宜吗?

那是因为香港服务器没有备案的烦恼,而且大陆也能轻松访问,有时候一些热点技术一出来,比如时下火热的 ai 技术,网站越快上线就能越早拿到搜索引擎排名,备案得等个把月,这一等就白白错失了很多成为下一个马总的机会。

docker的核心架构

Docker 采用经典的 客户端 - 服务器(C/S)分层架构,并遵循 OCI(开放容器倡议)标准做了深度解耦。整体可以分为用户交互层、核心服务层、容器运行时层、内核支撑层四个层级,各组件通过标准化接口协同,共同完成镜像构建、容器运行、资源隔离等核心能力。


一、整体架构总览

Docker 的核心交互链路是:用户 → Docker Client → Docker Daemon → containerd → runc → Linux 内核

  • 客户端负责接收指令,守护进程负责业务编排,containerd 负责容器生命周期管理,runc 负责真正调用内核创建容器。
  • 客户端与服务端通过 REST API 通信,支持本地 Unix 套接字(/var/run/docker.sock)或远程 TCP 连接,二者可以部署在同一台机器,也可以跨主机。

二、核心组件详解

1. Docker Client(客户端)

用户与 Docker 交互的入口,即日常使用的 docker 命令行工具。

  • 负责解析用户命令(如 docker rundocker builddocker pull),将其封装为 API 请求发送给 Docker Daemon。
  • 本身不做任何实际运算,只充当 “指令转发器”,支持同时连接多个远程 Docker 守护进程。

2. Docker Daemon(dockerd,守护进程)

运行在宿主机后台的核心服务进程,是 Docker 的 “调度大脑”。

  • 对外提供 REST API,响应所有客户端请求。
  • 管理 Docker 四大核心对象:镜像、容器、网络、数据卷
  • 负责镜像的构建、分发、本地存储,以及容器网络配置、存储挂载等环境编排。
  • 自身不直接创建容器,而是将容器运行时相关的底层工作下派给 containerd

3. containerd(容器运行时守护进程)

Docker 1.11 版本后从 dockerd 中拆分出的独立组件,现已捐赠给 CNCF,成为行业通用的容器运行时控制面标准。

  • 核心职责:接管容器完整生命周期(创建、启动、停止、删除、状态监控)。
  • 负责镜像拉取、本地镜像存储管理、容器底层执行环境配置。
  • 通过 gRPC 接口与上层 dockerd 通信,向下调用 runc 真正创建容器。
  • 简单理解:dockerd 管 “业务逻辑”,containerd 管 “容器运行的底层脏活累活”。

4. runc(OCI 运行时工具)

OCI(开放容器倡议)运行时规范的官方参考实现,是一个轻量级、无状态的 CLI 工具。

  • 核心职责:真正创建容器。它直接调用 Linux 内核的 Namespaces、Cgroups 等接口,构造出隔离的运行环境,启动容器内的 1 号进程。
  • 创建完容器后立即退出,容器的持续监控由 containerd 负责。

三、镜像与仓库体系

1. Docker 镜像(Image)

容器的 “静态运行模板”,本质是一个只读的分层文件系统

  • 分层结构:镜像由多层只读文件叠加而成,每一层对应 Dockerfile 中的一条指令(如 RUNCOPY)。
  • 联合文件系统:通过 UnionFS(默认驱动为 Overlay2)将多层文件挂载为一个统一视图,用户感知不到分层存在。
  • 写时复制(CoW):容器启动时,会在镜像最上层添加一个可读写层;所有文件修改只作用于该层,不会改动底层镜像,实现了镜像复用和秒级容器启动。

2. Docker Registry(镜像仓库)

集中存储、分发 Docker 镜像的服务。

  • 公共仓库:Docker Hub、阿里云镜像服务等。
  • 私有仓库:企业自建的 Harbor、Registry 等。
  • dockerd 通过 docker pull / docker push 与仓库交互,完成镜像的拉取和上传。

四、容器隔离的底层内核技术

容器本质是 “被特殊隔离的宿主机进程”,其隔离与资源限制能力完全依赖 Linux 内核特性。

1. Namespaces(命名空间):资源视图隔离

给容器套上 “视野围墙”,让容器内的进程看不到宿主机和其他容器的资源。

  • PID 命名空间:隔离进程 ID,容器内有独立的 1 号 init 进程。
  • NET 命名空间:隔离网络栈,容器拥有独立网卡、IP、端口、路由表。
  • IPC 命名空间:隔离进程间通信(信号量、共享内存、消息队列)。
  • MNT 命名空间:隔离文件系统挂载点,容器有独立的根目录。
  • UTS 命名空间:隔离主机名和域名。
  • USER 命名空间:隔离用户 ID,容器内 root 可映射为宿主机普通用户。

2. Control Groups(Cgroups):资源用量限制

限制容器可使用的宿主机物理资源,防止容器抢占全部宿主机资源。

  • 可限制:CPU 使用率、内存上限、磁盘 IO 速率、文件句柄数等。
  • 可计量:统计容器实际资源消耗量。
  • 可控制:批量冻结、重启容器内所有进程。

3. 联合文件系统(UnionFS)

支撑镜像分层、写时复制机制的核心文件系统技术,Docker 默认使用性能更优的 Overlay2 驱动。


五、网络与存储架构

网络架构

Docker 通过网络驱动实现容器间、容器与外部的通信,常见模式:

  • bridge(默认):容器连接到 docker0 虚拟网桥,通过 NAT 访问外网,借助 iptables 实现端口映射。
  • host:与宿主机共享网络命名空间,性能最高但隔离性最弱。
  • none:容器无外部网络,仅保留本地回环。
  • container:与另一个容器共享网络命名空间。

存储架构

  • 镜像层:只读,共享复用。
  • 容器可读写层:临时存储,容器删除后数据丢失。
  • 数据卷(Volume):持久化存储,直接挂载宿主机目录,生命周期独立于容器。

六、一次 docker run 的完整执行流程

以启动一个 Nginx 容器为例,完整链路如下:

  1. 用户执行 docker run nginx,客户端将命令转为 API 请求发送给 dockerd。
  2. dockerd 检查本地是否存在 Nginx 镜像;若不存在,向配置的镜像仓库拉取镜像到本地。
  3. 镜像就绪后,dockerd 将容器创建请求通过 gRPC 下发给 containerd。
  4. containerd 生成容器运行配置,调用 runc 工具。
  5. runc 调用 Linux 内核的 Namespaces 和 Cgroups 接口,创建隔离环境,启动 Nginx 进程。
  6. runc 执行完成后退出,containerd 接管容器的生命周期监控与管理。
  7. 后续的 docker stopdocker exec 等操作,均沿此链路逐层下发。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐