找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3057

积分

0

好友

456

主题
发表于 3 天前 | 查看: 31| 回复: 0

单体应用拆分成微服务后,确实能够实现快速开发迭代。但硬币的另一面是,因为拆解出来的小服务太多,反而导致了测试和部署的复杂度与成本直线上升。

想想看,在单体应用时代,一个 Spring Boot 工程,打包成一个 war 包,部署到 Linux 服务器的 Tomcat 里就完事了。而微服务架构下,哪怕只是修改一个业务需求,都可能牵扯到好几个微服务模块。这就意味着,所有被波及的代码都需要重新走一遍测试、打包、部署、上线的流程。对于现场运维的同事来说,这无疑是成倍增加的工作压力。

另一个现实问题是环境。微服务通常会在公有云上通过创建 ECS 实例进行扩容。但一个新的 ECS 实例,往往只包含最基本的操作系统,并没有运行 Java 程序所需的 JDK 环境。于是你不得不手动安装 JDK,更头疼的是,不同服务依赖的 JDK 版本还可能不一致。虽然多数团队会统一采用 JDK 8,但难免会遇到一些偏爱前沿技术的项目经理,想要尝试 JDK 21 这类长期稳定的大版本。

谁给你的勇气尝试新版本?

而容器技术,恰好就是为解决上述两个核心痛点(代码部署难、环境依赖不一致)而生的。时下最火的容器技术当属 Docker。许多开发者用了好几年,可能只知道它能将应用和依赖打包,然后发布到任何 Linux 服务器上运行,实现 “一次构建,到处运行” 。至于它内部究竟是如何工作的,与传统虚拟化有何不同,可能就知之甚少了。

一、深入理解 Docker 架构

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux 或 Windows 操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

简单来说,Docker 是对 Linux 容器技术的一种封装,提供了更简单易用的接口。它是目前最流行的 Linux 容器解决方案。

一个完整的 Docker 体系主要由以下七个核心部分组成:

  1. Docker Client 客户端:用户与 Docker 交互的入口。
  2. Docker Daemon 守护进程:提供 Docker Server,用于接收 Docker Client 的请求。Docker Server 通过路由(Router)与分发调度,找到相应的 Handler 来执行请求。
  3. Docker Image 镜像:包含 Distribution(分发)、Layer(层)、Image(镜像)、Registry(注册中心)、Reference(引用)。
  4. Docker Driver 驱动:通过与 Docker 守护进程交互,实现对 Docker 容器执行环境的定制和管理。
  5. Docker Graph 内部数据库:一种用于记录和跟踪 Docker 镜像和容器之间关系的数据结构。
  6. Libcontainer 函数库:Docker 的底层容器管理库,提供接口和函数用于创建和管理容器。它直接与内核交互,负责容器的命名空间、cgroup、网络设备等底层操作。
  7. Docker Container 容器:通过 Driver 和 Libcontainer 共同协作创建出来的容器实例。

Docker 详细架构图

二、Docker 架构工作流程详解

结合上图,我们可以梳理出 Docker 从接收命令到创建容器的完整工作流程:

  1. 用户使用 Docker Client 与 Docker Daemon 建立通信,并发送请求。客户端和守护进程之间通过 REST API 进行通信,可以使用 UNIX 套接字或网络接口。
  2. Docker Daemon 接收到请求后,其内部的 Docker Server 通过路由和分发,找到相应的 Handler 来处理。Docker Daemon 的核心是 Docker Engine,Engine 中的 Job 是最基本的工作执行单元,Docker 的每一项工作(如运行进程、创建容器)都被抽象为一个 Job。
  3. 当请求涉及镜像时(例如 docker run),流程会进入 Docker Image 模块。如果需要从远端获取镜像,则会与 Registry(如 Docker Hub)交互。
  4. 下载的镜像通过镜像管理驱动 graphdriver 以 Graph 的形式存储到本地。
  5. Docker Graph 作为内部数据库,记录了镜像的元数据和层级关系。一个 Registry 包含多个 Repository(仓库),一个 Repository 包含多个同类型但不同标签(Tag)的 Image。
  6. 容器的根文件系统(rootfs)由内核挂载为“只读”模式,然后通过“联合挂载”技术额外挂载一个“可写”层。
  7. 通过 networkdriver 完成 Docker 容器网络环境的配置,例如创建 Docker 网桥。
  8. execdriver 作为容器的执行驱动,负责创建容器运行命名空间,管理资源使用统计与限制,并真正启动容器内的进程。
  9. Libcontainer 是上述驱动的底层实现,它直接调用内核功能,完成命名空间隔离、cgroups 资源限制等操作。
  10. 最终,由 Driver 和 Libcontainer 共同协作,创建出可运行的 Docker Container 实例,实现服务交付。

说的什么玩意啊?是不是有点复杂?

1、Docker Client 客户端

Docker Client 是用户与 Docker 交互的主要命令行工具(CLI)。它的主要职责包括:

  • 提供交互界面:让用户通过命令管理容器和镜像。
  • 容器与镜像管理:执行创建、启动、停止、删除、查看等操作。
  • 资源配置:允许用户为容器配置 CPU、内存等资源。
  • 网络通信:作为客户端,与后端的 Docker Daemon 通信。

2、Docker Daemon 守护进程

Docker Daemon 是运行在宿主机上的后台服务,是 Docker 的核心。其主要作用包括:

  • 管理容器生命周期:响应客户端请求,负责容器的创建、运行、监控和销毁。
  • 镜像管理:处理镜像的拉取、构建、存储和删除。
  • 管理网络与存储:配置容器网络、管理数据卷等。

3、镜像(Image)的构成要素

在 Docker 镜像体系中,有几个关键概念:

  1. Distribution(分发):指镜像的传输方式,例如从 Registry 下载或通过文件导入导出。
  2. Layer(层):镜像是分层构建的,每一层都是只读文件系统。这种设计使得镜像层可以被复用,极大提升了存储和传输效率。
  3. Image(镜像):一个只读的模板,包含了运行应用所需的文件系统、依赖和配置。
  4. Registry(注册中心):集中存储和分发镜像的服务,如 Docker Hub、阿里云镜像仓库等。
  5. Reference(引用):标识特定镜像的方式,通常由仓库名、标签或镜像 ID 组成。

镜像的分层与数据湖概念示意图

三、Docker run 的流程与传统虚拟化对比

1、docker run 的完整流程

当你执行 docker run hello-world 时,背后发生了一系列事情:

Docker run 命令执行流程图

  1. Docker 客户端将 run 命令发送给守护进程。
  2. 守护进程首先在本地查找名为 hello-world:latest 的镜像。
  3. 如果本地没有,则去配置的 Registry(默认 Docker Hub)查找并下载。
  4. 下载成功后,以该镜像为模板,创建并启动一个新的容器。
  5. 容器执行预设的命令,输出结果,并通过守护进程流回客户端,显示在你的终端上。

2、与传统虚拟化方式对比

这是 Docker 性能远优于传统虚拟机(VM)的根本原因。两者架构对比如下:

传统虚拟化与 Docker 容器化架构对比图

核心差异

  • 抽象层:Docker 比虚拟机少了 Guest OS 这一层。它利用的是宿主机的内核,而每个 VM 都需要一个完整的客户机操作系统。
  • 性能与资源:更少的抽象层意味着更少的资源开销和更快的启动速度。Docker 容器是进程级别的隔离,而 VM 是操作系统级别的隔离。
  • 体积:Docker 镜像只包含应用及其依赖,体积通常以 MB 计;而 VM 镜像包含整个 OS,体积往往以 GB 计。

这种轻量级特性,使得 Docker 在实现 微服务 的快速部署和弹性伸缩方面具有天然优势。

四、Docker 安装实战(以 CentOS 为例)

1、卸载旧版本(如有)

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

2、安装必要工具包

yum install -y yum-utils

3、设置稳定的镜像仓库

推荐使用国内镜像源以加速下载:

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

更新 YUM 软件包索引:

yum makecache fast

4、安装 Docker 引擎

Docker CE 是社区免费版,EE 是企业版。这里安装 CE 版:

yum install docker-ce docker-ce-cli containerd.io

安装 Docker 相关组件的终端截图

5、启动 Docker 服务

systemctl start docker

6、验证安装

使用 docker version 命令检查客户端和服务器端版本,确认安装成功。

Docker version 命令输出截图

7、运行测试容器

执行著名的 hello-world 镜像,这将拉取镜像并运行一个测试容器,输出欢迎信息。

docker run hello-world

Hello from Docker! 运行结果截图

如果看到 “Hello from Docker!”,恭喜你,Docker 已经安装并运行正常。

五、Docker 常用命令速查表

为了方便日常使用,以下汇总了 Docker 的核心命令及其简要说明:

常用命令 命令含义
attach 连接到正在运行容器的标准输入/输出
build 通过 Dockerfile 构建镜像
commit 将容器的更改提交为新的镜像
cp 在容器和宿主机之间拷贝文件
create 创建一个新容器但不启动
diff 检查容器文件系统的更改
events 获取服务器的实时事件
exec 在运行中的容器内执行命令
export 将容器文件系统导出为 tar 包
history 显示镜像的历史记录
images 列出本地镜像
import 从 tar 包导入内容创建镜像
info 显示系统范围的信息
inspect 获取容器/镜像的详细信息
kill 强制停止一个运行中的容器
load 从 tar 包或 STDIN 加载镜像
login 登录到 Docker 仓库
logout 从 Docker 仓库登出
logs 获取容器的日志
pause 暂停容器中的所有进程
port 列出容器的端口映射
ps 列出容器
pull 从仓库拉取镜像或仓库
push 推送镜像或仓库到仓库
rename 重命名容器
restart 重启容器
rm 删除一个或多个容器
rmi 删除一个或多个镜像
run 创建并运行一个新容器
save 将镜像保存为 tar 包
search 在 Docker Hub 中搜索镜像
start 启动一个或多个已停止的容器
stats 动态显示容器资源使用统计
stop 停止一个运行中的容器
tag 为镜像创建标签
top 显示容器内运行的进程
unpause 恢复暂停的容器
version 显示 Docker 版本信息
wait 阻塞直到容器停止,然后打印退出代码

理解 Docker 的原理,能帮助我们在日常开发和运维中更好地使用它,定位问题,并设计出更合理的容器化方案。从单体应用到微服务,再到容器化部署,是现代软件交付演进的重要路径。希望这篇对 Docker 架构和原理的剖析,能让你在“会用”的基础上,更进一步地“懂它”。

如果你想与其他开发者交流更多关于容器化、运维自动化 的经验,欢迎来 云栈社区 一起探讨。




上一篇:微服务架构演进实战:从单体应用到分布式服务拆分全流程解析
下一篇:Nacos注册中心核心原理:临时与永久实例、心跳机制与集群一致性探析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-10 11:37 , Processed in 0.458184 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表