Docker入门|第2章 容器架构详解
摘要 :本章围绕 Docker 容器架构展开,先以 3W 框架(What、Why、How)讲清容器的定义、与虚拟机的区别及底层内核原理;再介绍 Docker 项目、版本演进与镜像/容器/仓库三大核心概念;随后详解 Docker 的 C/S 架构、七大组件与内部执行流程,最后以
docker run完整流程串联各组件协同工作,帮助读者建立 Docker 整体架构认知。
一、容器3W学习框架:What、Why、How
1.1 容器技术发展史
容器并不是Docker发明的,容器隔离思想很早就已经出现,关键发展时间线:
- 1979年 :Unix V7引入
Chroot Jail与chroot系统调用,实现进程根目录隔离,是最早容器化雏形;但root进程有逃逸风险,安全性弱。 - 1982年:chroot机制加入BSD系统。
- 2000年:FreeBSD推出FreeBSD Jail,增强chroot安全性,可以划分多个独立子系统,并分配独立IP。
- 2001年:Linux VServer问世,结合安全上下文,在单Linux内核运行多个发行版。
- 2004年:Solaris Containers,使用Zone区域实现资源边界隔离。
- 2006年:Google提出Process Containers,用于限制、统计进程组CPU/内存/磁盘IO/网络资源。
- 2007年:进程容器演变为cgroups,合并进入Linux内核2.6.24。
- 2008年:LXC(Linux Containers)诞生,结合cgroups + namespace,真正实现Linux容器管理器。
- 2013年:Docker正式发布,基于LXC,大幅优化用户体验,后续替换为自研libcontainer。
- 2014年:Google开源LMCTFY,把内部容器栈对外开源,代码概念贡献给libcontainer;同年CoreOS发布rkt容器。
1.2 What:什么是容器
容器是一种轻量级、可移植、自包含的软件打包技术,应用打包完成之后,几乎可以在任意环境无修改运行。开发笔记本、虚拟机、物理服务器、公有云主机,都可以直接跑同一个容器。
容器由两部分构成:
- 应用程序本身
- 应用运行全部依赖库、软件包
容器运行在宿主机Host OS用户空间,是一组被内核隔离的普通进程,共享宿主机内核。这点和虚拟机有着本质区别。
1.3 容器 vs 虚拟机对比
虚拟机通过Hypervisor虚拟化完整硬件,每一台虚拟机都拥有独立Guest操作系统;容器共享宿主机内核,只隔离用户空间。
| 特性 | 虚拟机 | 容器 |
|---|---|---|
| 启动速度 | 数分钟 | 秒级甚至毫秒级 |
| 系统内核 | 拥有独立Guest内核 | 共享宿主机Host内核 |
| 实现技术 | Hypervisor硬件虚拟化 | Linux Namespace + Cgroups内核技术 |
| 隔离效果 | 硬件级完整强隔离 | 进程级别隔离 |
| 资源消耗 | 开销大,完整操作系统占用大量内存磁盘 | 开销很小,只是宿主机普通进程 |
| 资源调用 | 应用需要经过Hypervisor拦截转发 | 进程直接调用宿主机操作系统 |
| 单机运行数量 | 单服务器一般几十台虚拟机 | 单机可以运行1000+容器 |
| 镜像特点 | 完整非分层操作系统镜像 | 分层只读镜像 |
| 典型使用场景 | 硬件强隔离、需要不同内核版本场景 | DevOps、微服务、环境一致性交付 |
| 硬盘占用 | GB级别 | MB级别 |
| 迁移性 | 一般 | 优秀 |
核心区别:虚拟机虚拟硬件;容器仅仅隔离进程,复用宿主机Linux内核。
1.4 Why:我们为什么需要容器
现代软件面临环境一致性难题: 业务系统越来越复杂,一个业务拆分为大量微服务,每个组件拥有各自依赖库。同时软件要跑在开发虚拟机、QA测试服务器、私有数据中心、公有云、笔记本电脑等多种多样硬件环境。
就形成一个N(服务) × M(运行环境)矩阵。开发要适配各种环境,运维要维护多套环境配置,工作量巨大,很容易出现"在我电脑能跑,线上跑不起来"。
现实类比:现实世界集装箱
过去货运行业同样遇到类似问题,不同货物形态不一样,装卸转运极其麻烦。集装箱标准化之后:不管里面装钢琴、汽车、货物,统一规格箱体;卡车、火车、轮船都可以统一装卸运输,到达目的地才开箱。
Docker借鉴集装箱思想,把软件、依赖全部打包到标准化"软件集装箱",也就是容器。
- 开发:在笔记本构建容器镜像;
- 测试:直接拉取镜像运行,环境和开发完全一致;
- 生产环境:直接部署同一个镜像,不需要修改。
| 对比项 | 现实集装箱 | Docker容器 |
|---|---|---|
| 打包对象 | 各类实体货物 | 软件 + 全部依赖库 |
| 硬件适配 | 标准箱体,任意交通工具转运 | 镜像可以在虚拟机、物理机、公有云运行 |
| 隔离能力 | 货物之间互相隔离,互不损坏 | 资源、网络、库版本互相隔离,消除依赖冲突 |
| 自动化 | 标准接口,起重机自动搬运 | 标准化run/start/stop命令,便于CI/CD自动化 |
| 高效性 | 不用开箱中转,快速转运 | 轻量级,秒级启动、快速迁移 |
| 职责划分 | 货主只关心装箱;运输方只负责运输 | 开发只写业务代码;运维只维护底层宿主机环境 |
对于开发者:Build Once,Run Anywhere,一次构建到处运行。 对于运维人员:Configure Once,Run Anything,配置一套标准runtime,就可以运行任意容器。 容器消除开发、测试、生产环境不一致的经典难题。
1.5 How:容器如何工作
容器底层依赖Linux两大内核能力:
- Namespace命名空间:实现隔离,容器看到独立主机名、网络、进程树、用户。
- Cgroups控制组:实现资源限制,限制容器CPU、内存、磁盘IO、网络最大使用量。
后续章节会深入展开底层原理;本章重点先掌握Docker整体架构。
二、Docker介绍
2.1 Docker项目简介
Docker是Go语言开发的开源容器项目,2013年由dotCloud公司发起;项目影响力巨大,dotCloud直接改名为Docker Inc,专注容器产品开发。
Docker核心价值:
- 提供完整工具链:镜像分发、版本管理、容器移植,屏蔽底层内核细节,降低容器使用门槛;
- 创新分层镜像机制,镜像复用,大幅降低镜像存储与传输开销;
- 把容器复杂内核能力封装成简单命令,用户操作容器就像操作普通应用程序。
Docker容器可以理解为轻量级沙盒:每个沙盒运行独立应用,容器互相隔离,容器之间也可以网络通信;容器创建销毁速度极快,资源开销极低。
2.2 Docker版本演进
Docker分为CE社区版(免费),EE企业版(商业付费)。
- 在17.03版本之前,Docker引擎版本号格式:
0.1.0 ~ 1.13.1; - 2017‑03‑02,Docker正式区分CE(Community Edition社区版)与EE(Enterprise Edition企业版),改用YY.MM年月式版本号;
- CE:每季度发布稳定版本,每个月发布Edge预览版本;季度版本维护4个月;
- EE企业版:季度发布,每个版本官方维护12个月。
版本号格式示例:17.03.0,YY.MM.patch;YY年份,MM月份,patch补丁序号。
2.3 Docker三大核心概念
2.3.1 镜像(Image)
Docker镜像属于只读模板,用来创建容器实例。例如Apache镜像,内置最小操作系统 + Apache Web服务。镜像支持增量分层构建,可以从互联网下载现成镜像,也可以自己编写Dockerfile构建。
2.3.2 容器(Container)
容器是镜像的运行实例。基于镜像启动得到容器;容器可以启动、停止、删除;容器之间互相隔离。
类比面向对象:镜像 = 类;容器 = 实例对象。
2.3.3 仓库(Repository / Registry)
镜像仓库是集中存放镜像的地方。一个仓库下面可以存放同一个软件不同tag版本镜像。分为公开仓库、私有仓库。
- Docker Hub:全球最大公开公共仓库;
- 阿里云、华为云SWR:国内公共镜像仓库;
- 用户可以自建私有Registry、Harbor私有仓库。
三、Docker架构详解
3.1 Docker整体C/S客户端‑服务端架构
Docker采用经典Client‑Server(C/S)架构。
- Docker Client(客户端) :
docker命令行CLI; - Docker Daemon(dockerd服务端守护进程):后台服务,真正干活; 两者之间使用REST API通信;可以本地socket通信,也可以跨机器远程TCP网络通信。
完整Docker七大组成组件:
- Docker Daemon守护进程dockerd:侦听API请求,管理镜像、容器、网络、数据卷;同时可以和其他主机daemon通信。
- REST API接口:客户端和daemon交互接口;CLI或者程序代码都可以调用这套API。
- Docker Client客户端:即docker命令,用户日常交互入口;发送REST API请求给dockerd执行任务。
- Registry镜像仓库:存放镜像,Docker Hub或者自建私有Harbor。
- Image镜像:只读模板,用来生成容器。
- Container容器:镜像运行实例,可以启停删除、挂载存储、配置网络,也可以基于容器制作新镜像。
- Services服务:Swarm集群模式组件,跨多台主机扩展容器副本,实现负载均衡。
3.2 Docker内部底层执行流程
- 用户执行
docker客户端命令,向Docker Daemon发送请求; - Docker Daemon内部Docker Server接收API请求;
- Docker Engine收到任务,每一项任务封装成为Job;
- Job需要镜像:访问Registry拉取镜像,graph驱动管理镜像分层存储;
- Job需要网络:network驱动配置容器网络;
- Job需要资源限制/执行命令:exec驱动执行;
- libcontainer底层库对接Linux内核:调用namespace、cgroups等内核接口真正创建容器。
3.3 Docker Client客户端
就是我们终端执行的docker命令工具,提供大量子命令。
bash
docker run # 创建运行容器
docker exec # 在运行容器执行命令
docker ps # 列出容器
docker build # 构建镜像
docker pull # 拉取镜像
docker push # 推送镜像
docker info # 查看系统整体信息
docker version # 查看版本
客户端不仅仅是命令行,第三方程序也可以直接调用REST API访问Docker服务端。
3.4 Docker Daemon服务端dockerd
dockerd是Linux后台守护服务进程。
bash
systemctl status docker.service
dockerd负责接收所有任务,管理镜像、容器、网络、存储卷全部对象。
注意:客户端与服务端可以部署不同机器,实现远程操作Docker,对应教案第一章的C/S分离部署实验。
3.5 镜像、容器、Registry回顾
- 镜像Image:只读模板,可以从网络下载,也可以Dockerfile构建;
- 容器Container:镜像运行实例,拥有可写容器层;
- Registry仓库:存放镜像,docker pull下载镜像,docker push上传镜像。
四、Docker组件如何协同工作(docker run完整流程)
以执行docker run -d -p 80:80 httpd为案例,完整拆解组件协同:
- 用户在客户端执行
docker run命令; - Docker Client把请求发送给本地dockerd守护进程;
- dockerd检查本地是否已经存在
httpd镜像; - 本地没有镜像,则向Docker Hub Registry发起拉取请求;
- Registry把httpd镜像分层下载,保存到本地;
- dockerd基于本地httpd镜像创建容器,配置端口映射、网络;
- 启动容器,httpd服务在容器内部运行。
执行完成后可以使用:
bash
docker images # 看到已经下载httpd镜像
docker ps # 看到正在运行httpd容器
五、第2章小结
- 容器技术不是Docker首创,拥有很长发展历史,从chroot、jail、cgroups、LXC一路演进,Docker简化使用体验普及容器。
- 容器是软件打包技术,共享宿主机内核;对比虚拟机,容器轻量、启动快、资源占用小。集装箱思想解决软件环境N×M矩阵难题,实现一次构建到处运行。
- Docker是C/S架构,Client客户端 + dockerd服务守护进程,REST API作为中间通信层;支持本地socket、远程TCP访问。
- 三大核心概念:镜像(只读模板)、容器(运行实例)、Registry镜像仓库。
- Docker内部执行链路:CLI → REST API → dockerd → engine Job → libcontainer → Linux内核namespace/cgroups。
- docker run完整流程:客户端发请求 → daemon检查本地镜像 → 缺失镜像从Registry拉取 → 创建并启动容器。