02.容器架构
第二章 容器架构:从原理到实操的深度解析
文章目录
- 第二章 容器架构:从原理到实操的深度解析
- 容器三问:What、Why、How
- 容器发展的 "进化史"
- What:到底什么是容器?
- 容器 vs 虚拟机:直观对比
- Why:为什么需要容器?解决 "环境一致性" 痛点
- Docker 的 "集装箱" 特性对应
- 007 Docker 架构:核心组件与工作原理
- Docker 的核心组件
- Docker 的工作流程:启动一个容器的全过程
- Docker 版本:CE 与 EE 的区别
- 008 动手实操:从零开始运行你的第一个容器
- 步骤 1:安装 Docker CE
- 步骤 2:拉取第一个镜像
- 步骤 3:启动第一个容器
- 步骤 4:验证容器运行状态
- 步骤 5:操作容器(启动、停止、删除)
- 步骤 6:删除镜像
- 小结:容器技术的核心价值
容器三问:What、Why、How
学习任何技术,都可以从最基础的三个问题入手:它是什么(What)?为什么需要它(Why)?它是如何工作的(How)?容器技术也不例外,咱们一步步揭开它的面纱。
容器发展的 “进化史”
容器技术并非一蹴而就,而是经过几十年的迭代才发展到今天的形态。咱们按时间线梳理下关键节点:
- 1979 年:Chroot Jail(雏形)
最早出现在 Unix V7 系统中,核心功能是 “改变根目录”(Change Root)。它能把一个进程及其子进程 “囚禁” 在指定目录下,让它们只能看到这个目录内的文件,无法访问系统其他部分。
举个例子:就像给进程画了个 “圈”,圈外的东西看不见,但 root 用户能轻易 “跳出圈子”,安全性很弱。 - 1982 年:Chroot 进入 BSD
被整合到 BSD 系统中,功能上没有大的突破,但开始被更多人使用。 - 2000 年:FreeBSD Jail(安全升级)
解决了 Chroot 的安全漏洞,不仅能隔离文件系统,还能给每个 “Jail(监狱)” 分配独立的 IP 地址和用户权限。
举个例子:相当于把一台服务器分成多个 “迷你服务器”,每个 Jail 里的应用互不干扰,管理员能单独管理。 - 2001 年:Linux VServer(跨发行版隔离)
首次实现了在单个 Linux 系统上运行多个不同的 Linux 发行版(比如在 CentOS 上跑 Ubuntu)。它结合了类似 Chroot 的隔离和 “安全上下文” 机制,让不同发行版的应用共存。 - 2004 年:Solaris Containers(资源控制)
引入 “区域(Zone)” 概念,不仅隔离进程,还能限制 CPU、内存等资源的使用。比如可以给某个容器分配 20% 的 CPU,避免它占用过多资源。 - 2006 年:cgroups(资源管理核心)
谷歌推出 Process Containers,2007 年改名为 cgroups(控制组),并被合并到 Linux 内核 2.6.24。它能精确控制一组进程的资源(CPU、内存、磁盘 I/O 等),是现代容器技术的核心底层技术。 - 2008 年:LXC(首个 Linux 容器管理器)
第一次把 cgroups 和 Linux 命名空间(Namespace,用于隔离进程 ID、网络等)结合起来,实现了完整的容器管理功能。用户可以通过 LXC 创建、启动、停止容器,但操作比较复杂。 - 2013 年:Docker 横空出世
基于 LXC 优化了用户体验,后来用自研的 libcontainer 替代 LXC,让容器操作变得简单易用。Docker 的出现真正让容器技术普及开来。 - 2014 年及以后:百花齐放
谷歌推出 LMCTFY(后并入 libcontainer)、CoreOS 推出 rkt,容器生态逐渐完善,最终 Kubernetes 成为容器编排的事实标准。
What:到底什么是容器?
一句话概括:容器是一种轻量级、可移植、自包含的软件打包技术,能让应用在任何环境中以相同方式运行。
拆解来看,容器包含两部分:
- 应用程序本身:比如一个 Java 后端服务、一个 Python 脚本。
- 应用依赖:比如 Java 运行时(JRE)、Python 库、配置文件、系统工具等。
容器的核心特点:
- 轻量级:不包含完整操作系统,只打包必要的依赖,体积通常是 MB 级(对比虚拟机的 GB 级)。
- 可移植:在开发电脑上创建的容器,无需修改就能放到服务器、云平台上运行。
- 隔离性:容器内的进程与主机及其他容器隔离,互不干扰(通过 Linux 命名空间实现)。
- 资源可控:能限制容器使用的 CPU、内存等资源(通过 cgroups 实现)。
容器 vs 虚拟机:直观对比
很多人会把容器和虚拟机混为一谈,其实两者的设计思路完全不同。咱们用架构图和表格对比下:
特性 | 容器(以 Docker 为例) | 虚拟机(以 VMware 为例) |
---|---|---|
底层依赖 | 共享主机操作系统内核 | 需安装完整操作系统(有独立内核) |
启动速度 | 秒级(比如启动 Nginx 容器约 0.1 秒) | 分钟级(启动 Windows 虚拟机约 30 秒) |
体积大小 | 通常几 MB 到几百 MB(如 Nginx 容器约 142MB) | 通常几 GB(如 Windows 10 虚拟机约 20GB) |
资源占用 | 低(1 台服务器可跑上千个容器) | 高(1 台服务器通常跑几十个虚拟机) |
隔离级别 | 进程级隔离(共享内核,隔离性较弱) | 完全隔离(独立内核,隔离性强) |
迁移难度 | 极简单(通过镜像复制) | 较复杂(需迁移整个虚拟机文件) |
举个实际场景:
如果要部署 10 个 Web 服务:
- 用虚拟机:需要 10 台虚拟服务器,每台安装操作系统、Web 服务器,耗时且占资源。
- 用容器:10 个容器共享主机内核,直接基于 Web 服务器镜像启动,几分钟搞定,资源占用仅为虚拟机的 1/10。
Why:为什么需要容器?解决 “环境一致性” 痛点
软件开发中,最头疼的问题之一就是 “环境不一致”:
- 开发环境:程序员的笔记本(Windows/macOS,各种自定义配置)。
- 测试环境:公司内部服务器(Linux,特定版本依赖)。
- 生产环境:公有云 / 私有云(可能是不同的 Linux 发行版,严格的权限控制)。
结果就是:“在我电脑上能跑啊!” 成了开发和运维的日常争吵。
容器如何解决这个问题?
它借鉴了集装箱思想:
- 运输行业的痛点:以前货物运输时,不同货物(香蕉、铁桶)需要不同的处理方式,换交通工具(卡车→轮船)时要重新装卸,效率低且易损坏。
- 集装箱的解决方案:统一标准的箱子,不管装什么货物,都能直接在各种交通工具间转移,无需重新打包。
容器对软件的作用,就像集装箱对货物的作用:
- 开发人员把应用和所有依赖 “装进” 容器,形成一个标准化的 “软件集装箱”。
- 这个容器可以在开发、测试、生产环境中无缝迁移,因为容器内的环境是完全一致的。
用矩阵图看容器的价值:
没有容器时,N 种服务和 M 种环境会形成 N×M 的适配难题(比如服务 A 在环境 1 正常,在环境 2 报错);有了容器后,只需确保容器能在环境中运行,服务与环境的适配问题被消除。
Docker 的 “集装箱” 特性对应
Docker 作为最流行的容器工具,完美体现了集装箱的设计思想:
集装箱特性 | Docker 对应功能 | 实际例子 |
---|---|---|
标准化包装 | 镜像(Image) | 一个mysql:8.0 镜像,包含 MySQL 8.0 及所有依赖,在哪都能跑 |
跨平台兼容 | 容器可在任何支持 Docker 的环境运行 | 本地开发的容器,直接部署到阿里云 ECS、腾讯云 CVM |
隔离不干扰 | 命名空间隔离(进程、网络、文件系统等) | 容器 A 的 MySQL 崩溃,不会影响容器 B 的 Nginx 服务 |
资源可控 | cgroups 资源限制 | 限制容器最多使用 1 核 CPU、2GB 内存 |
高效搬运 | 镜像仓库(Registry) | 从 Docker Hub 下载镜像,比手动安装快 10 倍 |
职责分工 | 开发打包镜像,运维管理容器 | 开发只关心代码,运维只关心容器运行环境 |
007 Docker 架构:核心组件与工作原理
Docker 采用客户端 - 服务器(C/S)架构,就像咱们用手机(客户端)给服务器发消息(请求),服务器处理后返回结果。咱们一步步拆解它的核心组件和工作流程。
Docker 的核心组件
Docker 的架构由以下几部分组成,缺一不可:
-
Docker 客户端(Client)
是用户与 Docker 交互的入口,通常是命令行工具(docker
命令),也可以是图形化界面(如 Docker Desktop)。
作用:接收用户输入的命令(如docker run
),并发送给 Docker daemon 处理。命令示例:
# 查看客户端版本 docker --version # 输出:Docker version 24.0.6, build ed223bc# 启动一个Nginx容器 docker run -d -p 80:80 nginx
-
Docker 守护进程(Daemon)
后台运行的服务(进程名为dockerd
),是 Docker 的 “大脑”。
作用:- 接收并处理客户端的命令(如创建容器、下载镜像)。
- 管理 Docker 的核心对象:镜像、容器、网络、存储卷。
- 与其他守护进程通信(比如在集群环境中)。
查看守护进程状态(Linux):
systemctl status docker # 输出中"active (running)"表示正在运行
-
Docker 镜像(Image)
是容器的 “模板”,一个只读的文件集合,包含运行应用所需的所有内容(代码、依赖、配置、环境变量等)。
特点:- 分层存储:镜像由多个只读层组成,复用相同的层(比如多个镜像都依赖 Ubuntu 底层,只存一份),节省空间。
- 不可修改:一旦创建就不能修改,若要修改需创建新的镜像层。
举例:
nginx:latest
镜像包含 Ubuntu 系统基础文件、Nginx 程序、默认配置等,基于它可以启动多个 Nginx 容器。 -
Docker 容器(Container)
是镜像的 “运行实例”,相当于从模板创建的 “可执行文件”。
与镜像的关系:就像 Java 中 “类” 和 “对象” 的关系(镜像是类,容器是对象)。
特点:- 可读写:容器在镜像的只读层上增加了一个可写层,所有修改都保存在这一层。
- 生命周期可控:可以被创建、启动、停止、重启、删除。
-
镜像仓库(Registry)
是存放 Docker 镜像的 “仓库”,类似代码仓库(如 GitHub)。
分类:- 公有仓库:最著名的是 Docker Hub(https://hub.docker.com/),包含数百万个公开镜像(如 Nginx、MySQL)。
- 私有仓库:企业或个人搭建的仓库(如 Harbor),用于存放私密镜像(如公司内部的业务系统镜像)。
Docker 的工作流程:启动一个容器的全过程
以docker run nginx
命令为例,看看 Docker 各组件是如何协作的:
- 用户输入命令:在终端执行
docker run nginx
(客户端发起请求)。 - 客户端转发请求:Docker 客户端将命令转换为 API 请求,发送给 Docker daemon。
- 检查本地镜像:Docker daemon 先检查主机上是否有nginx镜像:
- 若没有,就去默认的镜像仓库(Docker Hub)下载镜像(类似从网上下载软件安装包)。
- 若有,直接使用本地镜像。
- 创建并启动容器:Docker daemon 基于
nginx
镜像创建容器(在镜像只读层上添加可写层),并启动容器内的 Nginx 进程。 - 返回结果:容器启动成功后,Docker daemon 将结果返回给客户端,用户在终端看到输出。
Docker 版本:CE 与 EE 的区别
Docker 分为两个版本,适合不同场景:
- Docker CE(Community Edition):社区版,免费开源,适合个人开发者和小型团队。
- Docker EE(Enterprise Edition):企业版,收费,提供官方支持、安全增强等功能,适合大型企业。
版本号规则(2017 年 3 月后):
- 采用
YY.MM
格式(如 24.06 表示 2024 年 6 月发布)。 - 每季度发布一个稳定版(如 24.03、24.06),CE 版维护 4 个月,EE 版维护 12 个月。
- 每月发布一个 Edge 版(如 24.04、24.05),适合尝鲜新功能。
008 动手实操:从零开始运行你的第一个容器
理论讲完了,咱们动手实操,体验 Docker 的便捷。以下操作以 Linux(CentOS 7)为例,Windows/macOS 用户可安装 Docker Desktop,操作命令一致。
步骤 1:安装 Docker CE
# 1. 安装依赖工具
yum install -y yum-utils device-mapper-persistent-data lvm2# 2. 添加Docker软件源(阿里云,速度更快)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# 3. 安装Docker CE
yum install -y docker-ce docker-ce-cli containerd.io-ce docker-ce-cli containerd.io# 4. 启动Docker服务并设置开机自启
systemctl start docker
systemctl enable docker# 5. 验证安装(输出版本信息表示成功)
docker --version
步骤 2:拉取第一个镜像
从 Docker Hub 拉取nginx
镜像(Nginx 是常用的 Web 服务器):
docker pull nginx
执行后,终端会显示下载进度,类似:
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
...
Digest: sha256:xxxxxx
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
查看本地镜像:
docker images
# 输出类似:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 142MB
步骤 3:启动第一个容器
用nginx
镜像启动一个容器,并将容器的 80 端口映射到主机的 80 端口(这样就能通过主机 IP 访问容器内的 Nginx):
docker run -d -p 80:80 --name my-first-nginx nginx
参数说明:
-d
:后台运行容器( detach )。-p 80:80
:端口映射,格式为 “主机端口:容器端口”。--name my-first-nginx
:给容器起个名字(方便后续操作)。nginx
:指定要使用的镜像。
步骤 4:验证容器运行状态
# 查看正在运行的容器
docker ps
# 输出类似:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f47b353d4a7a nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp my-first-nginx
此时,在浏览器中输入主机的 IP 地址(如http://192.168.1.100
),就能看到 Nginx 的默认欢迎页面,说明容器运行正常!
步骤 5:操作容器(启动、停止、删除)
# 停止容器
docker stop my-first-nginx# 启动已停止的容器
docker start my-first-nginx# 重启容器
docker restart my-first-nginx# 查看所有容器(包括已停止的)
docker ps -a# 删除容器(需先停止)
docker rm my-first-nginx
步骤 6:删除镜像
# 删除nginx镜像(需先删除基于该镜像的所有容器)
docker rmi nginx
小结:容器技术的核心价值
容器技术的出现,彻底改变了软件的开发、测试和部署方式:
- 对开发人员:只需关注代码,不用关心环境差异(“Build Once, Run Anywhere”)。
- 对运维人员:只需维护容器运行环境,不用为每个应用配置依赖(“Configure Once, Run Anything”)。
- 对企业:缩短开发周期、降低运维成本、提高系统可靠性。
下一章,我们将深入学习 Docker 镜像的构建(通过 Dockerfile)和容器的高级操作,让你真正掌握容器技术的精髓!