结合下图,本文讨论docker 创建容器过程:
START└── [用户通过Docker Client发出指令]└── (1) docker run 或 docker create 命令├── (2) Docker Client与Docker Daemon建立通信连接└── (3) Docker Daemon接收到创建容器请求├── (4) 检查本地是否存在指定镜像│ ├── (4a) 存在:使用本地镜像│ └── (4b) 不存在:从Docker Registry拉取镜像├── (5) 镜像下载完成后,根据镜像元数据创建新的容器配置├── (6) 分配唯一的容器ID├── (7) 设置容器的网络配置├── (7a) 创建或加入网络(如桥接网络、overlay网络等)├── (7b) 配置端口映射、DNS等网络参数└── (7c) 设置容器间链接(如果适用)├── (8) 设置容器存储卷(如有必要)├── (8a) 绑定挂载宿主机目录├── (8b) 创建或使用数据卷容器└── (8c) 使用临时文件系统或存储驱动进行持久化存储├── (9) 初始化容器环境变量、用户、工作目录等配置└── (10) 准备容器运行时环境├── (10a) 创建容器命名空间、控制组(cgroups)、安全上下文等└── (10b) 启动容器进程(执行指定的ENTRYPOINT和CMD)└── (11) 容器运行时监控├── (11a) 监控容器资源使用情况(CPU、内存、磁盘、网络)├── (11b) 根据cgroups限制调整资源分配└── (11c) 处理容器生命周期事件(如重启、停止、退出)└── (12) 用户访问与交互├── 提供API接口供Docker Client查询容器状态、 logs等信息├── 支持通过`docker exec`命令进入容器执行命令└── 在容器终止时处理退出码及清理工作
注解:
1、 用户通过Docker客户端(如命令行界面CLI)执行docker run
或docker create
命令,指定要使用的镜像、运行参数等。
2、Docker客户端与Docker守护进程(Docker Daemon,即Docker Engine)建立远程API连接,以便发送请求和接收响应。
3、Docker守护进程接收到创建容器的请求后,开始处理该请求。
4、检查本地镜像仓库中是否已有指定的镜像。如果有,直接使用;如果没有,需从Docker Registry(如Docker Hub)拉取。
-
如果本地存在所需镜像,则跳过下载步骤。
-
如果本地不存在所需镜像,Docker会从注册表拉取镜像,并将其存储在本地镜像仓库。
5、根据选定的镜像元数据(如镜像层、环境变量、默认入口点等)生成新的容器配置。
6、为新容器分配一个唯一的容器ID。
7、设置容器的网络配置,包括但不限于:
- 将容器加入已有的网络(如桥接网络、overlay网络等)或创建新的网络。
- 配置端口映射,将容器内部端口暴露到宿主机或其他网络。
- 设置DNS解析规则和其他网络参数,确保容器间通信和对外访问。
8、设置容器的存储卷,用于持久化数据或共享数据:
- 可以将宿主机上的目录绑定挂载到容器内。
- 使用数据卷容器(Data Volume Container)共享数据。
- 通过临时文件系统(如tmpfs)或特定存储驱动(如devicemapper、overlay2等)管理持久化存储。
9、初始化容器的环境变量、用户、工作目录等运行时配置,即创建容器1号进程。
10、准备容器运行时环境:
- 创建必要的Linux命名空间(如PID、NET、MNT等)、控制组(cgroups)以实现资源隔离与限制,以及安全上下文(如SELinux标签)。
- 最后,启动容器主进程,执行镜像定义的ENTRYPOINT和CMD。
11、容器运行时监控:
- 监控容器的CPU、内存、磁盘、网络等资源使用情况。
- 根据cgroups设置对容器资源进行动态调整。
- 处理容器的生命周期事件,如自动重启、手动停止、异常退出等。
12、容器状态变更时,Docker守护进程将通知Docker客户端更新状态信息。
以上流程涵盖了从用户发起容器创建请求到容器实际运行起来的全过程,涉及的主要组件包括Docker Client、Docker Engine(Daemon)、镜像、容器运行时、网络配置、存储管理等。您可以根据此描述绘制详细的流程图来直观展现整个过程。